{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 10,
     "status": "ok",
     "timestamp": 1633470818726,
     "user": {
      "displayName": "Kevin Zou",
      "photoUrl": "https://lh3.googleusercontent.com/a/default-user=s64",
      "userId": "10683254170489198540"
     },
     "user_tz": -630
    },
    "id": "k_E0VELS4NP2",
    "is_executing": true,
    "outputId": "bd5504e2-3029-4c8f-deb4-050f885082d0"
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 422,
     "status": "ok",
     "timestamp": 1633470819145,
     "user": {
      "displayName": "Kevin Zou",
      "photoUrl": "https://lh3.googleusercontent.com/a/default-user=s64",
      "userId": "10683254170489198540"
     },
     "user_tz": -630
    },
    "id": "Qyy2IpTzbgF0",
    "is_executing": true,
    "outputId": "abf5f70f-e4b3-4640-ce87-c9166e390e2c"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mon Jan  1 10:52:33 2024       \n",
      "+---------------------------------------------------------------------------------------+\n",
      "| NVIDIA-SMI 546.33                 Driver Version: 546.33       CUDA Version: 12.3     |\n",
      "|-----------------------------------------+----------------------+----------------------+\n",
      "| GPU  Name                     TCC/WDDM  | Bus-Id        Disp.A | Volatile Uncorr. ECC |\n",
      "| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |\n",
      "|                                         |                      |               MIG M. |\n",
      "|=========================================+======================+======================|\n",
      "|   0  NVIDIA GeForce MX250         WDDM  | 00000000:06:00.0 Off |                  N/A |\n",
      "| N/A   45C    P0              N/A / ERR! |      0MiB /  2048MiB |      0%      Default |\n",
      "|                                         |                      |                  N/A |\n",
      "+-----------------------------------------+----------------------+----------------------+\n",
      "                                                                                         \n",
      "+---------------------------------------------------------------------------------------+\n",
      "| Processes:                                                                            |\n",
      "|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |\n",
      "|        ID   ID                                                             Usage      |\n",
      "|=======================================================================================|\n",
      "|  No running processes found                                                           |\n",
      "+---------------------------------------------------------------------------------------+\n"
     ]
    }
   ],
   "source": [
    "!nvidia-smi"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "IeZyx1-fcLXe"
   },
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "executionInfo": {
     "elapsed": 3,
     "status": "ok",
     "timestamp": 1633470819146,
     "user": {
      "displayName": "Kevin Zou",
      "photoUrl": "https://lh3.googleusercontent.com/a/default-user=s64",
      "userId": "10683254170489198540"
     },
     "user_tz": -630
    },
    "id": "GmBFBvfbOj0a",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "executionInfo": {
     "elapsed": 14736,
     "status": "ok",
     "timestamp": 1633470833880,
     "user": {
      "displayName": "Kevin Zou",
      "photoUrl": "https://lh3.googleusercontent.com/a/default-user=s64",
      "userId": "10683254170489198540"
     },
     "user_tz": -630
    },
    "id": "dPdpNulr5rdc",
    "is_executing": true,
    "outputId": "d5a8c364-2d45-4d02-cc80-b1e681c8e218"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python implementation: CPython\n",
      "Python version       : 3.11.3\n",
      "IPython version      : 8.19.0\n",
      "\n",
      "numpy       : 1.24.1\n",
      "pandas      : 2.1.4\n",
      "torch       : 2.1.2+cu118\n",
      "transformers: 4.36.2\n",
      "\n"
     ]
    }
   ],
   "source": [
    "%reload_ext watermark\n",
    "%watermark -v -p numpy,pandas,torch,transformers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "pEHKZt-qRG5x",
    "is_executing": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "device(type='cuda', index=0)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#@title Setup & Config\n",
    "import transformers\n",
    "from transformers import BertModel, BertTokenizer, AdamW, get_linear_schedule_with_warmup\n",
    "import torch\n",
    "import unicodedata\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import seaborn as sns\n",
    "from pylab import rcParams\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import rc\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import confusion_matrix, classification_report\n",
    "from collections import defaultdict\n",
    "from textwrap import wrap\n",
    "\n",
    "from torch import nn, optim\n",
    "from torch.utils.data import Dataset, DataLoader\n",
    "import torch.nn.functional as F\n",
    "from sklearn.metrics import f1_score\n",
    "from torch.nn import TransformerEncoder, TransformerEncoderLayer\n",
    "from collections import Counter\n",
    "import ast\n",
    "import random\n",
    "\n",
    "\n",
    "%matplotlib inline\n",
    "%config InlineBackend.figure_format='retina'\n",
    "\n",
    "sns.set(style='whitegrid', palette='muted', font_scale=1.2)\n",
    "\n",
    "HAPPY_COLORS_PALETTE = [\"#01BEFE\", \"#FFDD00\", \"#FF7D00\", \"#FF006D\", \"#ADFF02\", \"#8F00FF\"]\n",
    "\n",
    "sns.set_palette(sns.color_palette(HAPPY_COLORS_PALETTE))\n",
    "\n",
    "rcParams['figure.figsize'] = 12, 8\n",
    "\n",
    "RANDOM_SEED = 42\n",
    "np.random.seed(RANDOM_SEED)\n",
    "torch.manual_seed(RANDOM_SEED)\n",
    "\n",
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "device"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "HHAlx_DgsuY6"
   },
   "source": [
    "## New Section"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "AoiHKtRV8EwC",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "2O_HqSb1Bon0",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# sns.countplot(df.label_norm)\n",
    "# plt.xlabel('review score');"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "id": "xRdWcGGBFYTu",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "from transformers import BertTokenizer,BertModel\n",
    "PRE_TRAINED_MODEL_NAME = \"hfl/chinese-roberta-wwm-ext\"\n",
    "# PRE_TRAINED_MODEL_NAME = \"hfl/chinese-roberta-wwm-ext-large\"\n",
    "# PRE_TRAINED_MODEL_NAME = \"hfl/chinese-bert-wwm-ext\"\n",
    "# PRE_TRAINED_MODEL_NAME = \"bert-base-uncased\"\n",
    "# PRE_TRAINED_MODEL_NAME = \"ProsusAI/finbert\"\n",
    "# PRE_TRAINED_MODEL_NAME = \"bert-base-chinese\"\n",
    "\n",
    "tokenizer = BertTokenizer.from_pretrained(PRE_TRAINED_MODEL_NAME,do_lower_case=True)\n",
    "PRE_TRAINED_MODEL_NAME = '../ROBERT_4_model.bin'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "T1rFrEyLP5Il"
   },
   "source": [
    "## Map the position of LTP to Bert tokens"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "eg7yz0zXQujX"
   },
   "source": [
    "## Generating the masks of verb, A0, A1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "IWNPdn8fg4gG",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "c4joMCxJKR5a",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "df_train = pd.read_csv('../data/train.csv',sep='\\t')\n",
    "df_val = pd.read_csv('../data/val.csv',sep='\\t')\n",
    "df_test = pd.read_csv('../data/test.csv',sep='\\t')\n",
    "df_ood = pd.read_csv('../data/ood.csv',sep='\\t')\n",
    "\n",
    "df_train = df_train.drop(df_train.loc[df_train.verbA0A1.isna()].index)\n",
    "df_test = df_test.drop(df_test.loc[df_test.verbA0A1.isna()].index)\n",
    "df_val = df_val.drop(df_val.loc[df_val.verbA0A1.isna()].index)\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1.isna()].index)\n",
    "\n",
    "df_train = df_train.drop(df_train.loc[df_train.verbA0A1=='[]'].index)\n",
    "df_test = df_test.drop(df_test.loc[df_test.verbA0A1=='[]'].index)\n",
    "df_val = df_val.drop(df_val.loc[df_val.verbA0A1=='[]'].index)\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1=='[]'].index)\n",
    "\n",
    "def string_to_tuples_list(text):\n",
    "  if text is np.nan or text =='[]':\n",
    "    return []\n",
    "  text = ''.join(text.split('], ['))\n",
    "  tmp = eval(text.strip('[').strip(']'))\n",
    "  if not isinstance(tmp[0],tuple):\n",
    "    return [tmp]\n",
    "  return list(tmp)\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "for col in ['verb','A0','A1']:\n",
    "  df_train[col] = df_train[col].apply(string_to_tuples_list)\n",
    "  df_val[col] = df_val[col].apply(string_to_tuples_list)\n",
    "  df_test[col] = df_test[col].apply(string_to_tuples_list)\n",
    "  df_ood[col] = df_ood[col].apply(string_to_tuples_list)\n",
    "\n",
    "for col in ['stock_factors','verbA0A1']:\n",
    "# for col in ['verbA0A1']:\n",
    "  df_train[col] = df_train[col].apply(ast.literal_eval)\n",
    "  df_val[col] = df_val[col].apply(ast.literal_eval)\n",
    "  df_test[col] = df_test[col].apply(ast.literal_eval)\n",
    "  df_ood[col] = df_ood[col].apply(ast.literal_eval)\n",
    "\n",
    "\n",
    "\n",
    "def mask(df):\n",
    "  df = df.reset_index(drop = True)\n",
    "  df['verb_mask'] = 0\n",
    "  df['A0_mask'] = 0\n",
    "  df['A1_mask'] = 0\n",
    "  df['verb_mask'] = df['verb_mask'].astype('object')\n",
    "  df['A0_mask'] = df['A0_mask'].astype('object')\n",
    "  df['A1_mask'] = df['A1_mask'].astype('object')\n",
    "  for index,row in df.iterrows():\n",
    "\n",
    "    df.at[index,'stock_factors'] = [*map(float,df.loc[index,'stock_factors'])]\n",
    "    AV_num = 0\n",
    "    for k,col in enumerate(['verb','A0','A1']):\n",
    "      masks = []\n",
    "      for j in range(len(row['verbA0A1'])):\n",
    "        mask = np.zeros(299)\n",
    "        idx = []\n",
    "        for v in row['verbA0A1'][j][k]:\n",
    "          \n",
    "          idx = idx + [int(i) for i in range(v[0],v[0]+v[1])]\n",
    "        # idx = np.unique(idx).tolist()\n",
    "        counter = Counter(idx)\n",
    "\n",
    "        mask = [0 if counter[i]== 0 else 1/len(counter) for i in range(0,len(mask))]\n",
    "        mask.insert(0,0)\n",
    "        masks.append(mask)\n",
    "      AV_num = len(masks)\n",
    "      for i in range(10 - len(masks)):\n",
    "        masks.append(np.zeros(300))\n",
    "      while len(masks)>10:\n",
    "        masks.pop()\n",
    "      name = col+'_mask'\n",
    "      df.at[index,name] = np.array(masks)\n",
    "    if AV_num>10:\n",
    "      AV_num=10\n",
    "    df.loc[index,'AV_num'] = int(AV_num)\n",
    "  df.AV_num = df.AV_num.astype('int')\n",
    "  df.stock_factors = df.stock_factors.apply(np.array)\n",
    "  return df\n",
    "\n",
    "\n",
    "df_train = mask(df_train)\n",
    "df_test = mask(df_test)\n",
    "df_val = mask(df_val)\n",
    "df_ood = mask(df_ood)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "bnCu_pWRk8Ba",
    "is_executing": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>CODE</th>\n",
       "      <th>NAME</th>\n",
       "      <th>DATE</th>\n",
       "      <th>CREATED_DATE</th>\n",
       "      <th>text_a</th>\n",
       "      <th>DESCRIPTION</th>\n",
       "      <th>READ</th>\n",
       "      <th>MARKET</th>\n",
       "      <th>CHANGE</th>\n",
       "      <th>FIRST_DAY</th>\n",
       "      <th>...</th>\n",
       "      <th>verb_mask</th>\n",
       "      <th>A0_mask</th>\n",
       "      <th>A1_mask</th>\n",
       "      <th>AV_num</th>\n",
       "      <th>trade_date</th>\n",
       "      <th>open_close_chg</th>\n",
       "      <th>co_label</th>\n",
       "      <th>cc_label</th>\n",
       "      <th>stock_factors</th>\n",
       "      <th>label</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>600006</td>\n",
       "      <td>东风汽车</td>\n",
       "      <td>2021-04-02 16:37:00</td>\n",
       "      <td>2021-04-02 16:33:00</td>\n",
       "      <td>东风汽车公告，3月汽车销量为2.31万辆，上年同期为1.37万辆，同比增长68.74%；一季...</td>\n",
       "      <td>东风汽车公告，3月汽车销量为2.31万辆，上年同期为1.37万辆，同比增长68.74%；一季...</td>\n",
       "      <td>4155194.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.003175</td>\n",
       "      <td>2021-04-02</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>2</td>\n",
       "      <td>2021-04-02</td>\n",
       "      <td>0.134491</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>[-0.3020583603065712, -0.2981298667692732, -0....</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>601880</td>\n",
       "      <td>大连港</td>\n",
       "      <td>2021-01-11 18:47:00</td>\n",
       "      <td>2021-01-11 18:47:00</td>\n",
       "      <td>营口港公告，公司发布了《营口港务股份有限公司关于大连港股份有限公司换股吸收合并公司并募集配套...</td>\n",
       "      <td>营口港公告，公司发布了《营口港务股份有限公司关于大连港股份有限公司换股吸收合并公司并募集配套...</td>\n",
       "      <td>5379661.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.000000</td>\n",
       "      <td>2021-01-11</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>4</td>\n",
       "      <td>2021-01-11</td>\n",
       "      <td>0.210301</td>\n",
       "      <td>2.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>[-0.3868333706631927, -0.3828631887629431, -0....</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2271</td>\n",
       "      <td>东方雨虹</td>\n",
       "      <td>2021-02-07 16:55:00</td>\n",
       "      <td>2021-02-07 16:55:00</td>\n",
       "      <td>东方雨虹公告，非公开发行股票申请获得中国证监会核准批文。</td>\n",
       "      <td>东方雨虹公告，非公开发行股票申请获得中国证监会核准批文。</td>\n",
       "      <td>5442991.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>-0.014683</td>\n",
       "      <td>2021-02-05</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.11...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>1</td>\n",
       "      <td>2021-02-05</td>\n",
       "      <td>-1.108554</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>[0.5756114363380322, 0.5596214058343731, 0.558...</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>603486</td>\n",
       "      <td>科沃斯</td>\n",
       "      <td>2021-01-18 18:26:00</td>\n",
       "      <td>2021-01-18 18:18:00</td>\n",
       "      <td>科沃斯公告，公司持股4.12%的股东泰怡凱電器有限公司拟减持不超过1693.10万股，即不超...</td>\n",
       "      <td>科沃斯公告，公司持股4.12%的股东泰怡凱電器有限公司拟减持不超过1693.10万股，即不超...</td>\n",
       "      <td>5457064.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.045938</td>\n",
       "      <td>2021-01-18</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05, 0.0...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>1</td>\n",
       "      <td>2021-01-18</td>\n",
       "      <td>-3.260698</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>[1.8006385305400538, 1.7302126454124178, 1.655...</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>600319</td>\n",
       "      <td>ST亚星</td>\n",
       "      <td>2021-01-17 19:21:00</td>\n",
       "      <td>2021-01-17 19:20:00</td>\n",
       "      <td>ST亚星公告，公司收上交所问询函，此前公司称拟终止筹划重大资产重组暨签订现金收购景芝酒业白酒...</td>\n",
       "      <td>ST亚星公告，公司收上交所问询函，此前公司称拟终止筹划重大资产重组暨签订现金收购景芝酒业白酒...</td>\n",
       "      <td>5456051.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.049869</td>\n",
       "      <td>2021-01-15</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>2</td>\n",
       "      <td>2021-01-15</td>\n",
       "      <td>-3.283389</td>\n",
       "      <td>4.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>[-0.2663411732838291, -0.2732655989281695, -0....</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10152</th>\n",
       "      <td>600145</td>\n",
       "      <td>ST新亿</td>\n",
       "      <td>2021-10-22 19:56:00</td>\n",
       "      <td>2021-10-22 19:56:00</td>\n",
       "      <td>财联社10月22日电，*ST新亿公告，为完善公司上下游产业链、充分发挥业务协同效应，公司拟以...</td>\n",
       "      <td>财联社10月22日电，*ST新亿公告，为完善公司上下游产业链、充分发挥业务协同效应，公司拟以...</td>\n",
       "      <td>4101094.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.051402</td>\n",
       "      <td>2021-10-22</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>2</td>\n",
       "      <td>2021-10-22</td>\n",
       "      <td>-3.608760</td>\n",
       "      <td>3.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>[-0.4203033873993377, -0.4186988773845758, -0....</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10153</th>\n",
       "      <td>600556</td>\n",
       "      <td>天下秀</td>\n",
       "      <td>2021-08-16 18:01:00</td>\n",
       "      <td>2021-08-16 18:01:00</td>\n",
       "      <td>天下秀发布半年报，上半年营业收入21.51亿元，同比增长62.89%；净利润2.12亿元，同...</td>\n",
       "      <td>天下秀发布半年报，上半年营业收入21.51亿元，同比增长62.89%；净利润2.12亿元，同...</td>\n",
       "      <td>3474014.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.026824</td>\n",
       "      <td>2021-08-16</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.3333333333333333, 0.3333333333333333,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.333333333333...</td>\n",
       "      <td>1</td>\n",
       "      <td>2021-08-16</td>\n",
       "      <td>2.342080</td>\n",
       "      <td>4.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>[-0.3103613199188795, -0.3021849650921364, -0....</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10154</th>\n",
       "      <td>600436</td>\n",
       "      <td>片仔癀</td>\n",
       "      <td>2021-07-21 19:24:00</td>\n",
       "      <td>2021-07-21 19:18:00</td>\n",
       "      <td>片仔癀公告，公司控股股东九龙江集团计划15个交易日后的3个月内，通过集中竞价交易方式减持不超...</td>\n",
       "      <td>片仔癀公告，公司控股股东九龙江集团计划15个交易日后的3个月内，通过集中竞价交易方式减持不超...</td>\n",
       "      <td>3865616.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.030076</td>\n",
       "      <td>2021-07-21</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>1</td>\n",
       "      <td>2021-07-21</td>\n",
       "      <td>-2.701139</td>\n",
       "      <td>4.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>[7.393108504044611, 7.494173552530666, 7.49465...</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10155</th>\n",
       "      <td>2982</td>\n",
       "      <td>湘佳股份</td>\n",
       "      <td>2021-05-07 19:40:00</td>\n",
       "      <td>2021-05-07 19:40:00</td>\n",
       "      <td>湘佳股份公告，公司2021年4月销售活禽298.95万只，销售收入6138.70万元，销售均...</td>\n",
       "      <td>湘佳股份公告，公司2021年4月销售活禽298.95万只，销售收入6138.70万元，销售均...</td>\n",
       "      <td>4120895.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.004317</td>\n",
       "      <td>2021-05-07</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>2</td>\n",
       "      <td>2021-05-07</td>\n",
       "      <td>0.247811</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>[0.4058399063708051, 0.4076937866227962, 0.427...</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10156</th>\n",
       "      <td>600781</td>\n",
       "      <td>ST辅仁</td>\n",
       "      <td>2021-08-31 15:10:00</td>\n",
       "      <td>2021-08-30 20:13:00</td>\n",
       "      <td>财联社8月30日电，ST辅仁发布半年报，上半年归属于母公司所有者的净利润亏损2.94亿元，上...</td>\n",
       "      <td>财联社8月30日电，ST辅仁发布半年报，上半年归属于母公司所有者的净利润亏损2.94亿元，上...</td>\n",
       "      <td>3798845.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>-0.050139</td>\n",
       "      <td>2021-08-31</td>\n",
       "      <td>...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>[[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...</td>\n",
       "      <td>1</td>\n",
       "      <td>2021-08-31</td>\n",
       "      <td>-4.001741</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "      <td>[-0.4058427750124316, -0.4087848325644312, -0....</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>10157 rows × 41 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "         CODE  NAME                 DATE         CREATED_DATE  \\\n",
       "0      600006  东风汽车  2021-04-02 16:37:00  2021-04-02 16:33:00   \n",
       "1      601880   大连港  2021-01-11 18:47:00  2021-01-11 18:47:00   \n",
       "2        2271  东方雨虹  2021-02-07 16:55:00  2021-02-07 16:55:00   \n",
       "3      603486   科沃斯  2021-01-18 18:26:00  2021-01-18 18:18:00   \n",
       "4      600319  ST亚星  2021-01-17 19:21:00  2021-01-17 19:20:00   \n",
       "...       ...   ...                  ...                  ...   \n",
       "10152  600145  ST新亿  2021-10-22 19:56:00  2021-10-22 19:56:00   \n",
       "10153  600556   天下秀  2021-08-16 18:01:00  2021-08-16 18:01:00   \n",
       "10154  600436   片仔癀  2021-07-21 19:24:00  2021-07-21 19:18:00   \n",
       "10155    2982  湘佳股份  2021-05-07 19:40:00  2021-05-07 19:40:00   \n",
       "10156  600781  ST辅仁  2021-08-31 15:10:00  2021-08-30 20:13:00   \n",
       "\n",
       "                                                  text_a  \\\n",
       "0      东风汽车公告，3月汽车销量为2.31万辆，上年同期为1.37万辆，同比增长68.74%；一季...   \n",
       "1      营口港公告，公司发布了《营口港务股份有限公司关于大连港股份有限公司换股吸收合并公司并募集配套...   \n",
       "2                           东方雨虹公告，非公开发行股票申请获得中国证监会核准批文。   \n",
       "3      科沃斯公告，公司持股4.12%的股东泰怡凱電器有限公司拟减持不超过1693.10万股，即不超...   \n",
       "4      ST亚星公告，公司收上交所问询函，此前公司称拟终止筹划重大资产重组暨签订现金收购景芝酒业白酒...   \n",
       "...                                                  ...   \n",
       "10152  财联社10月22日电，*ST新亿公告，为完善公司上下游产业链、充分发挥业务协同效应，公司拟以...   \n",
       "10153  天下秀发布半年报，上半年营业收入21.51亿元，同比增长62.89%；净利润2.12亿元，同...   \n",
       "10154  片仔癀公告，公司控股股东九龙江集团计划15个交易日后的3个月内，通过集中竞价交易方式减持不超...   \n",
       "10155  湘佳股份公告，公司2021年4月销售活禽298.95万只，销售收入6138.70万元，销售均...   \n",
       "10156  财联社8月30日电，ST辅仁发布半年报，上半年归属于母公司所有者的净利润亏损2.94亿元，上...   \n",
       "\n",
       "                                             DESCRIPTION       READ  MARKET  \\\n",
       "0      东风汽车公告，3月汽车销量为2.31万辆，上年同期为1.37万辆，同比增长68.74%；一季...  4155194.0     1.0   \n",
       "1      营口港公告，公司发布了《营口港务股份有限公司关于大连港股份有限公司换股吸收合并公司并募集配套...  5379661.0     1.0   \n",
       "2                           东方雨虹公告，非公开发行股票申请获得中国证监会核准批文。  5442991.0     0.0   \n",
       "3      科沃斯公告，公司持股4.12%的股东泰怡凱電器有限公司拟减持不超过1693.10万股，即不超...  5457064.0     1.0   \n",
       "4      ST亚星公告，公司收上交所问询函，此前公司称拟终止筹划重大资产重组暨签订现金收购景芝酒业白酒...  5456051.0     1.0   \n",
       "...                                                  ...        ...     ...   \n",
       "10152  财联社10月22日电，*ST新亿公告，为完善公司上下游产业链、充分发挥业务协同效应，公司拟以...  4101094.0     1.0   \n",
       "10153  天下秀发布半年报，上半年营业收入21.51亿元，同比增长62.89%；净利润2.12亿元，同...  3474014.0     1.0   \n",
       "10154  片仔癀公告，公司控股股东九龙江集团计划15个交易日后的3个月内，通过集中竞价交易方式减持不超...  3865616.0     1.0   \n",
       "10155  湘佳股份公告，公司2021年4月销售活禽298.95万只，销售收入6138.70万元，销售均...  4120895.0     0.0   \n",
       "10156  财联社8月30日电，ST辅仁发布半年报，上半年归属于母公司所有者的净利润亏损2.94亿元，上...  3798845.0     1.0   \n",
       "\n",
       "         CHANGE   FIRST_DAY  ...  \\\n",
       "0      0.003175  2021-04-02  ...   \n",
       "1      0.000000  2021-01-11  ...   \n",
       "2     -0.014683  2021-02-05  ...   \n",
       "3     -0.045938  2021-01-18  ...   \n",
       "4     -0.049869  2021-01-15  ...   \n",
       "...         ...         ...  ...   \n",
       "10152 -0.051402  2021-10-22  ...   \n",
       "10153  0.026824  2021-08-16  ...   \n",
       "10154 -0.030076  2021-07-21  ...   \n",
       "10155  0.004317  2021-05-07  ...   \n",
       "10156 -0.050139  2021-08-31  ...   \n",
       "\n",
       "                                               verb_mask  \\\n",
       "0      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "1      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "2      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "3      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "4      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "...                                                  ...   \n",
       "10152  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "10153  [[0.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0,...   \n",
       "10154  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "10155  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "10156  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "\n",
       "                                                 A0_mask  \\\n",
       "0      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "1      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.5,...   \n",
       "2      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.11...   \n",
       "3      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.05, 0.0...   \n",
       "4      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "...                                                  ...   \n",
       "10152  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "10153  [[0.0, 0.3333333333333333, 0.3333333333333333,...   \n",
       "10154  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "10155  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5,...   \n",
       "10156  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...   \n",
       "\n",
       "                                                 A1_mask  AV_num  trade_date  \\\n",
       "0      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       2  2021-04-02   \n",
       "1      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       4  2021-01-11   \n",
       "2      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       1  2021-02-05   \n",
       "3      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       1  2021-01-18   \n",
       "4      [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       2  2021-01-15   \n",
       "...                                                  ...     ...         ...   \n",
       "10152  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       2  2021-10-22   \n",
       "10153  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.333333333333...       1  2021-08-16   \n",
       "10154  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       1  2021-07-21   \n",
       "10155  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       2  2021-05-07   \n",
       "10156  [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,...       1  2021-08-31   \n",
       "\n",
       "       open_close_chg  co_label cc_label  \\\n",
       "0            0.134491       0.0      1.0   \n",
       "1            0.210301       2.0      3.0   \n",
       "2           -1.108554       0.0      1.0   \n",
       "3           -3.260698       0.0      0.0   \n",
       "4           -3.283389       4.0      4.0   \n",
       "...               ...       ...      ...   \n",
       "10152       -3.608760       3.0      2.0   \n",
       "10153        2.342080       4.0      4.0   \n",
       "10154       -2.701139       4.0      4.0   \n",
       "10155        0.247811       0.0      1.0   \n",
       "10156       -4.001741       0.0      0.0   \n",
       "\n",
       "                                           stock_factors  label  \n",
       "0      [-0.3020583603065712, -0.2981298667692732, -0....      1  \n",
       "1      [-0.3868333706631927, -0.3828631887629431, -0....      1  \n",
       "2      [0.5756114363380322, 0.5596214058343731, 0.558...      0  \n",
       "3      [1.8006385305400538, 1.7302126454124178, 1.655...      0  \n",
       "4      [-0.2663411732838291, -0.2732655989281695, -0....      0  \n",
       "...                                                  ...    ...  \n",
       "10152  [-0.4203033873993377, -0.4186988773845758, -0....      0  \n",
       "10153  [-0.3103613199188795, -0.3021849650921364, -0....      2  \n",
       "10154  [7.393108504044611, 7.494173552530666, 7.49465...      0  \n",
       "10155  [0.4058399063708051, 0.4076937866227962, 0.427...      1  \n",
       "10156  [-0.4058427750124316, -0.4087848325644312, -0....      0  \n",
       "\n",
       "[10157 rows x 41 columns]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_ood"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "xYTC1elyHlS7",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# from ltp import LTP\n",
    "# ltp = LTP()\n",
    "# a = tokenizer.tokenize(df_train.loc[4,'text_a'])\n",
    "# for idx,i in enumerate(df_train.verb_mask[4][2]):\n",
    "#   if i != 0:\n",
    "#     print(a[idx-1])\n",
    "# seg,hidden = ltp.seg([df_train.loc[4,'text_a']])\n",
    "# srl = ltp.srl(hidden)\n",
    "# def list_to_string(a):\n",
    "#   return ''.join(a)\n",
    "# for i,s in enumerate(srl[0]):\n",
    "#   if len(s)!=0:\n",
    "#     print(f'verb: {seg[0][i]} arv: ({[[ar[0], list_to_string([str(seg[0][k]) for k in range(ar[1],ar[2]+1)])] for ar in srl[0][i]]})')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "AmtpSQB2PTkC",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# df_train.shape, df_val.shape, df_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "ajOfqpcWRBt9"
   },
   "source": [
    "## Creat Dataloader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "ch_klsfERBI6",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "WaKd7JaTy2gw",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "max_len = 300\n",
    "class_names = ['negative','neutral', 'positive']\n",
    "class GPReviewDataset(Dataset):\n",
    "\n",
    "  def __init__(self, reviews, targets,verb,A0,A1,AV_num,tokenizer,stock_factors, max_len):\n",
    "    self.reviews = reviews\n",
    "    self.targets = targets\n",
    "    self.stock_factors = stock_factors\n",
    "    self.verb = verb\n",
    "    self.A0 = A0\n",
    "    self.A1 = A1\n",
    "    self.AV_num = AV_num\n",
    "    self.tokenizer = tokenizer\n",
    "    self.max_len = max_len\n",
    "  \n",
    "  def __len__(self):\n",
    "    return len(self.reviews)\n",
    "  \n",
    "  def __getitem__(self, item):\n",
    "    review = str(self.reviews[item])\n",
    "    target = self.targets[item]\n",
    "    stock_factors = self.stock_factors[item]\n",
    "    v = self.verb[item]\n",
    "    a0 = self.A0[item]\n",
    "    a1 = self.A1[item]\n",
    "    av_num = self.AV_num[item]\n",
    "\n",
    "    encoding = self.tokenizer.encode_plus(\n",
    "      review,\n",
    "      add_special_tokens=True,\n",
    "      max_length=self.max_len,\n",
    "      return_token_type_ids=False,\n",
    "      padding='max_length',\n",
    "      truncation=True,\n",
    "      return_attention_mask=True,\n",
    "      return_tensors='pt',\n",
    "    )\n",
    "\n",
    "    return {\n",
    "      'review_text': review,\n",
    "      'input_ids': encoding['input_ids'].flatten(),\n",
    "      'attention_mask': encoding['attention_mask'].flatten(),\n",
    "      'targets': torch.tensor(target, dtype=torch.long),\n",
    "      'stock_factors':torch.tensor(stock_factors),\n",
    "      'verb': torch.tensor(v),\n",
    "      'A0': torch.tensor(a0),\n",
    "      'A1': torch.tensor(a1),\n",
    "      'AV_num': torch.tensor(av_num)\n",
    "    }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "cPZSIigpPtEr",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "def create_data_loader(df, tokenizer, max_len, batch_size):\n",
    "  ds = GPReviewDataset(\n",
    "    reviews=df.text_a.to_numpy(),\n",
    "    targets=df.label.to_numpy(),\n",
    "    stock_factors = df.stock_factors,\n",
    "    verb = df.verb_mask,\n",
    "    A0 = df.A0_mask,\n",
    "    A1 = df.A1_mask,\n",
    "    AV_num = df.AV_num,\n",
    "    tokenizer=tokenizer,\n",
    "    max_len=max_len\n",
    "  )\n",
    "\n",
    "  return DataLoader(\n",
    "    ds,\n",
    "    batch_size=batch_size,\n",
    "    # num_workers=4,\n",
    "    shuffle=True\n",
    "  )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "4bMEUzcABFvn",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "BATCH_SIZE = 2 # TODO\n",
    "\n",
    "\n",
    "df_train = df_train.reset_index(drop=True)\n",
    "df_test = df_test.reset_index(drop=True)\n",
    "df_val = df_val.reset_index(drop=True)\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "\n",
    "\n",
    "\n",
    "train_data_loader = create_data_loader(df_train, tokenizer, max_len, BATCH_SIZE)\n",
    "val_data_loader = create_data_loader(df_val, tokenizer, max_len, BATCH_SIZE)\n",
    "test_data_loader = create_data_loader(df_test, tokenizer, max_len, BATCH_SIZE)\n",
    "ood_data_loader = create_data_loader(df_ood, tokenizer, max_len, BATCH_SIZE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "vDjd-DrAUt-d",
    "is_executing": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['review_text', 'input_ids', 'attention_mask', 'targets', 'stock_factors', 'verb', 'A0', 'A1', 'AV_num'])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data = next(iter(train_data_loader))\n",
    "data.keys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "bidtjT6UEKkk",
    "is_executing": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Some weights of BertModel were not initialized from the model checkpoint at ../ROBERT_4_model.bin and are newly initialized: ['bert.pooler.dense.weight', 'bert.pooler.dense.bias']\n",
      "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
     ]
    }
   ],
   "source": [
    "bert_model = BertModel.from_pretrained(PRE_TRAINED_MODEL_NAME)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "hsRtLnPlWulS",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "class SentimentClassifier(nn.Module):\n",
    "\n",
    "  def __init__(self, n_classes):\n",
    "    super(SentimentClassifier, self).__init__()\n",
    "    self.bert = BertModel.from_pretrained(PRE_TRAINED_MODEL_NAME)\n",
    "    self.encoder_layer =  nn.TransformerEncoderLayer(d_model=2304, nhead=1)\n",
    "    self.transformer_encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=2)\n",
    "    self.drop = nn.Dropout(p=0.1)\n",
    "    self.sig = nn.Sigmoid()\n",
    "    self.out1 = nn.Linear((self.bert.config.hidden_size*3)*10, (self.bert.config.hidden_size*3)*3)\n",
    "    self.out = nn.Linear((self.bert.config.hidden_size*3)*3, n_classes)\n",
    "    self.flatten2 = nn.Flatten(2,-1)\n",
    "    self.flatten = nn.Flatten(1,-1)\n",
    "    self.relu = nn.ReLU()\n",
    "    self.Querry = nn.Linear(self.bert.config.hidden_size,self.bert.config.hidden_size)\n",
    "    self.Key = nn.Linear(self.bert.config.hidden_size,self.bert.config.hidden_size)\n",
    "\n",
    "\n",
    "  \n",
    "  def forward(self, input_ids, attention_mask,verb,A0,A1,AV_num):\n",
    "    hidden_state = self.bert(\n",
    "      input_ids=input_ids,\n",
    "      attention_mask=attention_mask\n",
    "    )[0]\n",
    "    batch = hidden_state.shape[0]\n",
    "    \n",
    "    tmp_mask = torch.unsqueeze(verb,3)\n",
    "    tmp_mask = torch.cat(768 * [tmp_mask],3)\n",
    "    transformer_input = torch.mean(tmp_mask*torch.unsqueeze(hidden_state,1),2,True)\n",
    "\n",
    "    tmp_mask = torch.unsqueeze(A0,3)\n",
    "    tmp_mask = torch.cat(768 * [tmp_mask],3)\n",
    "    tmp_mask = torch.mean(tmp_mask*torch.unsqueeze(hidden_state,1),2,True)\n",
    "    transformer_input = torch.cat([transformer_input,tmp_mask],2)\n",
    "\n",
    "    tmp_mask = torch.unsqueeze(A1,3)\n",
    "    tmp_mask = torch.cat(768 * [tmp_mask],3)\n",
    "    tmp_mask = torch.mean(tmp_mask*torch.unsqueeze(hidden_state,1),2,True)\n",
    "    transformer_input = torch.cat([transformer_input,tmp_mask],2)\n",
    "\n",
    "    transformer_input = self.flatten2(transformer_input.float())\n",
    "    transformer_input = torch.stack([transformer_input[:,i,:] for i in range(0,len(A0[0]))])\n",
    "    transformer_output = self.transformer_encoder(transformer_input)\n",
    "    transformer_output = torch.stack([torch.squeeze(transformer_output[:,i,:]) for i in range(0,batch)])\n",
    "    transformer_output = torch.squeeze(transformer_output)\n",
    "\n",
    "    if transformer_output.dim()==2:\n",
    "      transformer_output = torch.unsqueeze(transformer_output,0)\n",
    "\n",
    "    output = self.flatten(transformer_output.float())\n",
    "    output = self.sig(output)\n",
    "#     output = self.drop(output)\n",
    "    output = self.out1(output)\n",
    "    output = self.sig(output)\n",
    "    output = self.drop(output)\n",
    "    output = self.out(output)\n",
    "\n",
    "    return output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "KQEOV2pfYBPs",
    "is_executing": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Some weights of BertModel were not initialized from the model checkpoint at ../ROBERT_4_model.bin and are newly initialized: ['bert.pooler.dense.weight', 'bert.pooler.dense.bias']\n",
      "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n",
      "C:\\root\\repos\\PycharmProjects\\stock-predict\\venv\\Lib\\site-packages\\torch\\nn\\modules\\transformer.py:282: UserWarning: enable_nested_tensor is True, but self.use_nested_tensor is False because encoder_layer.self_attn.batch_first was not True(use batch_first for better inference performance)\n",
      "  warnings.warn(f\"enable_nested_tensor is True, but self.use_nested_tensor is False because {why_not_sparsity_fast_path}\")\n"
     ]
    }
   ],
   "source": [
    "model = SentimentClassifier(3)\n",
    "model = model.to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "IfJO5a0NGPf_",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "uLl-umJKYGtB",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# input_ids = data['input_ids'].to(device)\n",
    "# attention_mask = data['attention_mask'].to(device)\n",
    "# verbs = data['verb'].to(device)\n",
    "# A0s = data['A0'].to(device)\n",
    "# A1s = data['A1'].to(device)\n",
    "# AV_num = data['AV_num'].to(device)\n",
    "# print(input_ids.shape) # batch size x seq length\n",
    "# print(attention_mask.shape) # batch size x seq length"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "VX0A_axjYJfP",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# F.softmax(model(input_ids, attention_mask,verb = verbs,A0 = A0s,A1 =A1s,AV_num = AV_num), dim=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "82irQeXrOfWI",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "4q2fUr9TYMxW",
    "is_executing": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\root\\repos\\PycharmProjects\\stock-predict\\venv\\Lib\\site-packages\\transformers\\optimization.py:429: FutureWarning: This implementation of AdamW is deprecated and will be removed in a future version. Use the PyTorch implementation torch.optim.AdamW instead, or set `no_deprecation_warning=True` to disable this warning\n",
      "  warnings.warn(\n"
     ]
    }
   ],
   "source": [
    "EPOCHS = 10\n",
    "\n",
    "optimizer = AdamW(model.parameters(), lr=1e-5, correct_bias=False)\n",
    "total_steps = len(train_data_loader) * EPOCHS\n",
    "\n",
    "scheduler = get_linear_schedule_with_warmup(\n",
    "  optimizer,\n",
    "  num_warmup_steps=0,\n",
    "  num_training_steps=total_steps\n",
    ")\n",
    "\n",
    "loss_fn = nn.CrossEntropyLoss().to(device)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "OYA1f6t3f2ex"
   },
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "oLLFWDvDYeeS",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "def train_epoch(\n",
    "  model, \n",
    "  data_loader, \n",
    "  loss_fn, \n",
    "  optimizer, \n",
    "  device, \n",
    "  scheduler, \n",
    "  n_examples\n",
    "):\n",
    "  model = model.train()\n",
    "\n",
    "  losses = []\n",
    "  correct_predictions = 0\n",
    "\n",
    "  for d in data_loader:\n",
    "    input_ids = d[\"input_ids\"].to(device)\n",
    "    attention_mask = d[\"attention_mask\"].to(device)\n",
    "    targets = d[\"targets\"].to(device)\n",
    "    verb = d[\"verb\"].to(device)\n",
    "    A0 = d[\"A0\"].to(device)\n",
    "    A1 = d[\"A1\"].to(device)\n",
    "    AV_num = d[\"AV_num\"].to(device)\n",
    "\n",
    "    outputs = model(\n",
    "      input_ids=input_ids,\n",
    "      attention_mask=attention_mask,\n",
    "      verb = verb,\n",
    "      A0 = A0,\n",
    "      A1 = A1,\n",
    "      AV_num = AV_num\n",
    "    )\n",
    "\n",
    "    _, preds = torch.max(outputs, dim=1)\n",
    "\n",
    "    # print(targets.shape,outputs.shape)\n",
    "    loss = loss_fn(outputs, targets)\n",
    "    print(loss)\n",
    "    correct_predictions += torch.sum(preds == targets)\n",
    "    losses.append(loss.item())\n",
    "\n",
    "    loss.backward()\n",
    "    nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)\n",
    "    optimizer.step()\n",
    "    scheduler.step()\n",
    "    optimizer.zero_grad()\n",
    "\n",
    "  return correct_predictions.double() / n_examples, np.mean(losses)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "VmDYxiXDYl-u",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "def eval_model(model, data_loader, loss_fn, device, n_examples):\n",
    "  model = model.eval()\n",
    "\n",
    "  losses = []\n",
    "  correct_predictions = 0\n",
    "\n",
    "  with torch.no_grad():\n",
    "    for d in data_loader:\n",
    "      input_ids = d[\"input_ids\"].to(device)\n",
    "      attention_mask = d[\"attention_mask\"].to(device)\n",
    "      targets = d[\"targets\"].to(device)\n",
    "      verb = d[\"verb\"].to(device)\n",
    "      A0 = d[\"A0\"].to(device)\n",
    "      A1 = d[\"A1\"].to(device)\n",
    "      AV_num = d[\"AV_num\"].to(device)\n",
    "\n",
    "      outputs = model(\n",
    "        input_ids=input_ids,\n",
    "        attention_mask=attention_mask,\n",
    "        verb = verb,\n",
    "        A0 = A0,\n",
    "        A1 = A1,\n",
    "        AV_num = AV_num\n",
    "      )\n",
    "\n",
    "      if outputs.dim()==1:\n",
    "        outputs = torch.unsqueeze(outputs,0)\n",
    "      _, preds = torch.max(outputs, dim=1)\n",
    "\n",
    "      loss = loss_fn(outputs, targets)\n",
    "\n",
    "      correct_predictions += torch.sum(preds == targets)\n",
    "      losses.append(loss.item())\n",
    "\n",
    "  return correct_predictions.double() / n_examples, np.mean(losses)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "Nkvo-2p93Dnr",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "history = defaultdict(list)\n",
    "best_accuracy = 0\n",
    "# EPOCHS = 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "VZvKK2TkYojZ",
    "is_executing": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "----------\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "File \u001b[1;32m<timed exec>:6\u001b[0m\n",
      "Cell \u001b[1;32mIn[20], line 16\u001b[0m, in \u001b[0;36mtrain_epoch\u001b[1;34m(model, data_loader, loss_fn, optimizer, device, scheduler, n_examples)\u001b[0m\n\u001b[0;32m     13\u001b[0m correct_predictions \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m     15\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m d \u001b[38;5;129;01min\u001b[39;00m data_loader:\n\u001b[1;32m---> 16\u001b[0m   input_ids \u001b[38;5;241m=\u001b[39m \u001b[43md\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minput_ids\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mto\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdevice\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m     17\u001b[0m   attention_mask \u001b[38;5;241m=\u001b[39m d[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mattention_mask\u001b[39m\u001b[38;5;124m\"\u001b[39m]\u001b[38;5;241m.\u001b[39mto(device)\n\u001b[0;32m     18\u001b[0m   targets \u001b[38;5;241m=\u001b[39m d[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mtargets\u001b[39m\u001b[38;5;124m\"\u001b[39m]\u001b[38;5;241m.\u001b[39mto(device)\n",
      "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "%%time\n",
    "\n",
    "for epoch in range(EPOCHS):\n",
    "\n",
    "  print(f'Epoch {epoch + 1}/{EPOCHS}')\n",
    "  print('-' * 10)\n",
    "\n",
    "  train_acc, train_loss = train_epoch(\n",
    "    model,\n",
    "    train_data_loader,    \n",
    "    loss_fn, \n",
    "    optimizer, \n",
    "    device, \n",
    "    scheduler, \n",
    "    len(df_train)\n",
    "  )\n",
    "\n",
    "  print(f'Train loss {train_loss} accuracy {train_acc}')\n",
    "\n",
    "  val_acc, val_loss = eval_model(\n",
    "    model,\n",
    "    val_data_loader,\n",
    "    loss_fn, \n",
    "    device, \n",
    "    len(df_val)\n",
    "  )\n",
    "\n",
    "  print(f'Val   loss {val_loss} accuracy {val_acc}')\n",
    "  print()\n",
    "\n",
    "  history['train_acc'].append(train_acc)\n",
    "  history['train_loss'].append(train_loss)\n",
    "  history['val_acc'].append(val_acc)\n",
    "  history['val_loss'].append(val_loss)\n",
    "\n",
    "  if val_acc > best_accuracy:\n",
    "    torch.save(model.state_dict(), 'Pretrained_RoBert_SRL(FC)-tuning.bin')\n",
    "    best_accuracy = val_acc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "FIyLcNepYr4f",
    "is_executing": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(history[\"train_acc\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "xu7Y2BPzLZgi",
    "is_executing": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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5hlNmTLFdE3m2cbF7dvZ2Vlz587VhAkTjHBeyph1/fjjj+urr74yAua8+l6wYIEOHz5slHv27KnvvvtOzZs3N653dXXVQw89pJCQEDVq1KhE7iE/LVu21NKlS9W3b1/T1gC1atXSjBkzdN999xnnoqOjtXPnziL1ExISYhw3bdpUs2bNUoMGDUzvnbu7ux577DHNnTvXtEXCTz/9VKQ+r0tPT9ekSZNM2zS89dZbmj59uu6++25jDBaLRY0bN9bnn3+u8ePHG3WvXr2qsWPHZluWP6vr4XyNGjU0a9Ys7d69W1u2bNGnn36q4cOHS5KcnJzUo0cP45qDBw/q5MmTebb7+++/Gw+BODo6qlevXoW4ewAAAAAoOwT0AAAAAIDbnrOzs7799lv16tVL3t7e8vHxUadOnTR48GCjzu+//24KI19//fV89wEfPHiwKbw/depUiY351VdfzXP2cs+ePU37hO/fv7/E+h42bJjatWuX6+stWrTQPffcY5T/+usvpaammuqkpaXp66+/Nsq1atXSv//971zfU29vb02fPl0eHh7FHH3e3N3d9dFHH6lChQq51nn22WdN5UOHDhWpr4iICOO4WbNmxsMgOWnYsKE6duwoJyenXGfEF8aKFSt07Ngxozxo0CDT5z0nTz31lPr162eUjx07pjVr1uTbl7e3t+bPn68uXbrI09NTlStX1sMPP2wK5bPOgF++fHmebWZ+6KN9+/YF2rMeAAAAAG4EBPQAAAAAgNveww8/rLp16+ZZ57777tP06dM1btw4PfPMMwWaze3u7i5fX1+jnHkv7+JwdnZW7969862XeU/uzHuZF9eAAQMK1XdaWpri4uJMr2/fvl3nz583yk8//bRcXFzybLN69erq27dvIUdbON26dVPVqlXzrHPnnXfK2dnZKGdeor8wMj8EsGHDBiUkJORZ/4MPPtD+/fu1fv16ffrpp0Xq87rMy/Q7Oztr9OjRBbruxRdfND10UpCVGQYPHpxvgF6/fn01aNDAKK9YsSLXuhcuXDC2IpBY3h4AAADAzYWAHgAAAABw22vbtm2+dQIDA439uV9++eUCtZs1lM46i7yogoODTUuv5ybzwwHXrl0rkb69vb1Vo0aNQvUtybSUuiRTwCpJ999/f4H67969e4HqFVXmBwty4+TkJG9vb6Nc1AcvWrRoYRyfPHlSffv2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nTtXTz31lF599dU8HxA4fPiwJkyYoEOHDmV77ezZszp79qzWrFmjxo0ba+rUqQoICMixncuXL+udd97RqlWrsr126dIlbd26VVu3btWcOXP04Ycfqm3btgW865KRlpamUaNGGYG9lPF+RkVFaeDAgaa6a9as0fvvv6+oqKhs7VitVsXHx+vMmTNat26dZs6cqWnTpmUL+LNasGCBPvnkEyUmJprOx8fH6/Dhwzp8+LDmz59v/MwcHDIWHL///vvl6emphIQE2Ww2/fbbb3r66afz7Ot6vet69+6dZ31AYol7AAAAAAAAAACAm5q/v786dOigDh06mM7fddddxvncZrNv3bpVs2fPzvG1Hj16GMcHDx7UkCFDTOG8r6+vmjVrprZt26phw4ZycXExXktOTtaUKVNyDJELa8+ePXrmmWeMcD4wMFCtW7dWcHCwKRDfu3evnn/++WL3d+bMGT322GOmcN7b21tNmzZV69at1ahRI9NM7rS0NH311VeaN29envfw+OOPm8J5d3d3NW7cWE2aNFH58uWN8/v379eQIUN08eLFbO1cunRJgwYNMr2vjo6OatCggVq2bKnKlSsb58+fP69Ro0Zp+/bthX8TimHmzJmmcP46X19ftWvXzij/+OOPevHFF03hfI0aNdSqVSu1bt1aNWvWNMJzKePBkZEjR+rMmTO59v3BBx9o8uTJpnC+WrVqatWqlWrXri0np4y5y+np6Zo7d64mTZpk1HNzc1O3bt2M8ooVK/K91507dxrj9/Hx0b333pvvNQAz6AEAAAAAAAAAAG5i7du3V/v27SWZlyIfN25ctqXIs1q/fr0kqWPHjnr11VcVGBio48ePa8OGDQoODpaUEWZOnDhRcXFxkjIC8ilTpqhVq1amtpKSkrRw4UJNnTpVVqtVkjRr1ix17969WPc3Z84cSVKzZs301ltvqUGDBsZrx48f17hx43Tw4EFJ0u7du7Vx40bdd999Re7vvffe07lz5yRlBPNTpkxRp06d5ODgoKSkJNlsNqWmpur333/X+++/r4SEBEnSV199pWHDhhkh8HVxcXF64YUXlJSUJEkqV66cxo0bp/79+8vV1VVSxjLv3377raZNm6a0tDSdPXtWkydPzrZc+vjx43XixAmjPHjwYI0ePVo+Pj7Gud9//11vv/22Ll26pJSUFL322mtau3at0Vdp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GRmp+Ph445oqVaooOjraeDDkwoULqly5sqndbt26adSoUZozZ44kaffu3erRo4fuuOMOValSRXFxcTpy5IhpG4KXXnpJLVu2zHO8PXv21LRp00z73rO8PYqDGfQAAAAAAAAAAAC3iP/7v/+Tk9P/n5/5119/aceOHdq9e3eR2+zTp49eeOEF0/LvMTEx2rdvn/bu3WsK4IODg7Vw4ULTTO89e/YUuW97a9Omjd59911ToB0XF6e//vpLu3fvNoXzAQEBmjdvnh577DHj3N69e3Nst3Hjxlq4cKHq169vnIuNjdXu3bu1a9cuUzj/wAMP6JtvvjH2jM+sYsWKWrhwobp162acS0lJUVhYmLZv324K54ODgzV//nzVq1cvWzs+Pj76+uuvFRAQYJxLSkrSgQMHFBYWZoTz3bt31/Tp00t0Br0kTZo0SZ06dTKdO3PmjHbu3KlDhw6Zwvn7779fy5YtM81Yz+19fvXVV/XWW2+Z3rvw8HCFhobq0KFDRjjv5uamSZMm6Zlnnsl3rFWrVjXtUe/m5qbu3bsX7EaBHDCDHgAAAAAAAAAA4BbRqlUrffPNN5ozZ44OHjyouLi4HIPewnr++efVqVMnLVy4UDt37lR0dLRSUlLk4eGhKlWqqGHDhurUqZO6du0qBwcHderUSUuXLpUkbdq0STExMfLx8Sn2OOyhf//+atGihX744QeFhobq9OnTunbtmjw8PFSpUiUFBwerXbt26tu3r1xcXOTj46PPPvtMUsYDEceOHctxT/O6detq2bJlWrt2rdauXav9+/fr0qVLstls8vPzU/PmzdWvX798Z3SXL19e06dP1759+/Trr79q+/btio6O1rVr1+Tt7a0777xTDz30kB566CHTwxpZNWrUSCtXrtSSJUu0du1a/fPPP0pMTFTlypV11113qV+/frr33nuL92bmwtXVVV9++aXWrVunX375RQcOHDDeiwoVKigoKEh33nmnHnnkETVp0kSS1KlTJ/33v/+VJC1btkyDBw/Ose3Bgwere/fuWrp0qf73v/8pPDxcsbGxKleunO644w516NBBgwYNyjYDPy9du3ZVaGiopIwHBkridwq3L4st6yYhQAEkJCToyJEjRrlevXp8GQG3gbCwMFmtVjk7O+vuu+8u6+EAwE2H71EAKB6+RwGg+PguxbFjx5SamionJ6ccA0QAeUtKSpLNZpPFYpG7u3tZDwd2MnbsWC1fvlySNG/ePHXo0KGMR4T8lMTfd6WVh7LEPQAAAAAAAAAAAADkIDExUevXr5eUsa1Bu3btynhEuNkR0AMAAAAAAAAAAABADn7++WclJSVJkgYOHCgHB+JVFA+fIAAAAAAAAAAAAADIYu/evZo6daokycPDQwMHDizjEeFW4FTWAwAAAAAAAAAAAACAshYZGakRI0aoatWqiomJ0dGjR43XXn75ZXl7e5fd4HDLIKAHAAAAAAAAAAAAcNurUqWKIiMjFRERYTr/0EMPafDgwWU0KtxqCOgBAAAAAAAAAAAA3PacnZ11//33KzQ0VFarVTVq1NCjjz6qxx9/nL3nUWII6AEAAAAAAAAAAABA0owZM8p6CLjF8agHAAAAAAAAAAAAAAB2QEAPAAAAAAAAAAAAAIAdENADAAAAAAAAAAAAAGAHBPQAAAAAAAAAAAAAANgBAT0AAAAAAAAAAAAAAHZAQA8AAAAAAAAAAAAAgB0Q0AMAAAAAAAAAAAAAYAcE9AAAAAAAAAAAAAAA2AEBPQAAAAAAAAAAAAAAdkBADwAAAAAAAAAAAACAHRDQAwAAAAAAAAAAAABgBwT0AAAAAAAAAAAAAADYAQE9AAAAAAAAAAAAAAB2QEAPAAAAAAAAAAAAAIAdENADAAAAAAAAAAAAAGAHBPQAAAAAAAAAAAAAANgBAT0AAAAAAAAAAAAAAHZAQA8AAAAAAAAAAIBSNXToUNWrV0/16tXTjBkzsr0+Y8YM4/WhQ4cWu7/t27cb7dWrV6/Y7RXWhg0b9Oeff+b4WkhIiDGuzp0723lkAMoaAT0AAAAAAAAAAABQAs6ePavnnntOzz77rKKjo8t6OABuQE5lPQAAAAAAAAAAAADgVjB8+HCFh4eX9TAA3MCYQQ8AAAAAAAAAAACUAKvVWtZDAHCDYwY9AAAAAAAAAAAAytSYMWM0ZsyYsh6GXfTt21d9+/Yt62EAKCPMoAcAAAAAAAAAAAAAwA4I6AEAAAAAAAAAAAAAsAOWuAcAAAAAAAAAALiJLV++XGPHjpUkubi4aNu2bfL09Mz3urfeekuLFy+WJHXs2FFz5szJsV5oaKg2btyoXbt2KTo6WrGxsXJ0dJSXl5eCgoLUpk0b9e/fX/7+/kW+hxkzZmjmzJmSpFatWun777/Pta7VatWvv/6qlStX6uDBg0pISJCvr68aN26swYMHq1WrVoXu//jx41qzZo22b9+uyMhIXb58WVarVV5eXvL391fLli3Vo0cP1apVK9u127dv1xNPPJHt/IQJEzRhwgRJ0ujRo40l/ENCQozzAQEB2rBhQ55jO3PmjJYsWaLQ0FBFREQoISFB5cuXV0BAgNq3b6/evXurZs2aebbRuXNnnTlzRpK0Z88eeXh46MSJE1q6dKk2b96sc+fOyWq1ys/PT61bt1b//v3VuHHj/N+4QkhPT9fGjRu1efNm7dmzR5cuXVJsbKxcXFzk5eWl2rVrq127durXr5+8vLwK1ObVq1e1fPlyrVu3TocOHVJsbKycnZ1VtWpVNW/evMD3YbPZtHHjRv3222/av3+/oqOjJUmVKlXSXXfdpYcfflj333+/HB0ds11b2J9n1s/LkSNHstWpV6+eJMnb29v4TE6dOlV//vmnUlJS5OfnpxYtWuj5559XtWrVTNfGxMRo5cqVCg0N1dGjRxUbG6vExER5enrKx8dHTZo0UZcuXdSlSxdZLJZ83xtJCg8P108//aRt27YpPDxcV69elaenp+rUqaN77rlHjz76qHx8fEzXZP5+qVGjhtauXVugvgYMGKCwsDBJ0ptvvqkhQ4YU6LqbCQE9AAAAAAAAAADATez++++Xu7u7kpKSlJKSonXr1ql37955XmO1WrVmzRqj3LNnz2x1jhw5ojfffFP79+/PsY2rV6/q3Llz2rFjh2bPnq1XX31VTz75ZLHuJT9HjhzRSy+9pBMnTpjOR0VFKSoqSqtXr9Zjjz2mBx98sEDtxcXF6e2339bq1auVnp6e7fWLFy/q4sWLOnjwoL799lv16NFDEydOlIuLS4ncT15SUlI0depUfffdd0pNTTW9FhMTo5iYGB04cEBz587V448/rtdee63A4/r66681depUpaSkmM5HREQoIiJCP/74owYOHKi3335bDg7FX5B7x44dmjRpko4fP57tNavVqsTERJ09e1abN2/W559/rvfee0/du3fPs801a9bonXfe0aVLl7K1d/z4cR0/flxLlixRnz599M4778jV1TXHdg4fPqwJEybo0KFD2V47e/aszp49qzVr1qhx48aaOnWqAgICCnHnxRcVFaXHH39cFy5cMM6Fh4fr7Nmzev31141zNptNM2fO1Ndff62kpKRs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dUnI/Fm+cOGCXn75ZUVFRZnqxMfHa8GCBerbt6/Onj1rei2n97hWrVqmBz3mzZunN998UzExMaZ6YWFheuKJJ4xVA3x8fEwP02Tl7++vtm3bGmM9c+aMpIyHhoq7+sTNxCn/KgAAAAAAAAAAALjZ9OrVK9ty8N27d5ezs3Ou11gsFr3wwgt6/fXXJWWE+2PHjtWUKVMUFBQki8Wi06dPm5aId3V1lYeHhxHeZX6tJL311lsKDw/X33//LZvNplmzZunbb7819ls/fPiwrl69Kknq2rWrfv/991zb+r//+z+tWbNG165dk5QRqs6fP181atSQp6enoqOjFRkZaXowoVq1aka4mXX59uvq1q2rPXv2SJLWrFmjRx55RD4+PmrTpo2ee+65At/r22+/rcjISO3cuVOStG7dOq1bt0516tRRpUqVdPnyZR07dsw0vkaNGhkB8I3Aw8NDI0eO1IwZMyRl7PU+cuRI+fv7q3r16kpJSdHp06d1+fJl4xovLy9ZrVYjNM7ps9S4cWP961//0uTJk2Wz2XTs2DENGjRIAQEBql69upKSknT48GHT7PtHH31UvXv3NrXj5eWladOmacSIEYqPj9eVK1f02muvacqUKapdu7YsFouOHj2quLg445pGjRrpjTfeyDamF198USNGjFB6errS09M1efJkzZw5UzVr1lR8fLxOnjxpjGfMmDFauHBhrp+hwurZs6dpZv7GjRvVtWtXBQYGytfXVzExMTp16pRppnxBPsuvvfaajhw5YqyQsWTJEoWEhKhevXoqX768oqKiFBERYdR3cXHRp59+anpIJSe9evXSli1bTOey/mxudcygBwAAAAAAAAAAuAU1btxYd9xxh+lcz549872uT58+euGFF+Tg8P9jpJiYGO3bt0979+41habBwcFauHChOnfubJy7HlCXNB8fH82fP9+0R3tSUpL27t2rvXv3GuF8x44d9d577+XZVu3atTV9+nSVL1/e1Nbff/+tnTt36tSpU0b4XbFiRX3yySd66aWXjLoHDhzIcdn54cOHy93d3SgfO3ZM27dvz3ergKzc3Nz09ddfa8iQIaZZ3//884+2b9+uo0ePGv07Ojpq0KBBmj9/vipUqFCofkrbc889p4EDB5rORUdHa/fu3Tpw4IApnG/RooV++ukn02z03D5LgwYN0meffWbac/3MmTPa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AAAAAADADgjoAQAAAAAAAAAAAACwAwJ6AAAAAAAAAAAAAADsgIAeAAAAAAAAAAAAAAA7IKAHAAAAAAAAAAAAAMAOCOgBAAAAAAAAAAAAALADAnoAAAAAAAAAAAAAAOyAgB4AAAAAAAAAAAAAADsgoAcAAAAAAAAAAAAAwA4I6AEAAAAAAAAAAAAAsAMCegAAAAAAAAAAAAAA7ICAHgAAAAAAAAAAAAAAOyCgBwAAAAAAAAAAAADADgjoAQAAAAAAAAAAAACwAwJ6AAAAAAAAAAAAAADsgIAeAAAAAAAAAAAAAAA7IKAHAAAAAAAAAAAAAMAOCOgBAAAAAAAAAAAAALADAnoAAAAAAAAAAAAAAOyAgB4AAAAAAAAAAAAAADsgoAcAAAAAAAAAAAAAwA4I6AEAAAAAAAAAAAAAsAMCegAAAAAAAAAAAAAA7ICAHgAAAAAAAAAAAAAAOyCgBwAAAAAAAAAAAADADgjoAQAAAAAAAAAAAACwAwJ6AAAAAAAAAAAAAADsgIAeAAAAAAAAAAAAAAA7IKAHAAAAAAAAAAAAAMAOCOgBAAAAAAAAAAAAALADAnoAAAAAAAAAAAAAAOyAgB4AAAAAAAAAAAAAADsgoAcAAAAAAAAAAAAAwA4I6AEAAAAAAAAAAAAAsAMCegAAAAAAAAAAAAAA7ICAHgAAAAAAAAAAAAAAOyCgBwAAAAAAAAAAAADADgjoAQAAAAAAAAAAAACwAwJ6AAAAAAAAAAAAAADsgIAeAAAAAAAAAAAAAAA7IKAHAAAAAAAAAAAAAMAOCOgBAAAAAAAAAAAAALADAnoAAAAAAAAAAAAAAOyAgB4AAAAAAAAAAAAAADsgoAcAAAAAAAAAAAAAwA4I6AEAAAAAAAAAAAAAsAMCegAAAAAAAAAAAAAA7ICAHgAAAAAAAAAAAAAAOyCgBwAAAAAAAAAAAADADgjoAQAAAAAAAAAAAACwAwJ6AAAAAAAAAAAAAADsgIAeAAAAAAAAAAAAAAA7IKAHAAAAAAAAAAAAAMAOCOgBAAAAAAAAAAAAALADAnoAAAAAAAAAAAAAAOyAgB4AAAAAAAAAAAAAADsgoAcAAAAAAAAAAAAAwA4I6AEAAAAAAAAAAAAAsAMCegAAAAAAAAAAAAAA7ICAHgAAAAAAAAAAAAAAOyCgBwAAAAAAAAAAAADADgjoAQAAAAAA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gEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAW0ae0FvFk89dRTueWWWzJt2rQsXLgwlUolu+66aw499NAMGTIkhx56aIvM+6c//Sl33XVXfvOb32ThwoVZsWJFunfvngMPPDDHHHNMTjrppLRr165F5gYAAAAAAACg+Qj0m7Fu3bpceeWVGTNmTKrV6kbfzZkzJ3PmzMnYsWNz6qmn5sILL0yHDh2aZd6VK1dmxIgRuf32298w74svvpgpU6ZkypQpGT16dL7//e9n//33b5Z5AQAAAAAAAGgZXnG/GRdeeGFuuOGGWiTv0KFD3v3ud+fggw/eKMaPHTs255xzTtatW9fkOVeuXJlhw4bltttuq83bsWPHvOtd78phhx2Wbt261c6dM2dO/vVf/zXPPvtsk+cFAAAAAAAAoOUI9P/E+PHjM27cuNrxZz7zmTz88MO5/fbbc9ttt+Xhhx/OaaedVvv+wQcfzOjRo5s870UXXZRHH300SVKpVHLmmWfm17/+de64447ceOONeeSRR3LxxRfXXm2/dOnSfPOb32zyvAAAAAAAAAC0HIF+E1atWpWrrrqqdvzxj388F110UTp37lz7rHPnzjn//PMzbNiw2mejRo3KsmXLtnreqVOn5u67707yepy/7LLL8pWvfGWjedu0aZNPf/rTGT58eO2z6dOn5/e///1WzwsAAAAAAABAyxLoN2HSpEl54YUXkrwe4s8777xNnnvWWWeld+/eSZJly5ZttOu+sUaNGlUbn3DCCTn11FM3ee6pp56aPffcs3b84IMPbvW8AAAAAAAAALQsgX4TJk2aVBsPHDhwox3s/6iuri5Dhgxp8NrGeP755zN16tQkSdu2bfOf//mfm73m7LPPzhlnnJGvfe1r6dev31bNCwAAAAAAAEDLa9PaC9gWVavVTJs2rXZ8xBFHbPaaww8/vDaeMWNGFi9enB133LFR8/7qV79KtVpNkhx55JHp2bPnZq856aSTGjUHAAAAAAAAAK3DDvoGzJs3L8uXL68dv/Od79zsNfvuu2/q6uqSvB74n3rqqUbP+8QTT9TGffv2bfT1AAAAAAAAAGy77KBvwNy5c2vjSqWSXr16bfaatm3bpmfPnlmwYEGS5K9//Wuj5501a1ZtvPfeeydJVq9enUmTJmXixIl5+umns2jRonTv3j0HHXRQPvrRj+aYY45p9DwAAAAAAAAAlCfQN+Cll16qjbt37562bdtu0XU77bRTLdC/+OKLjZ533rx5tfEuu+ySP//5zznvvPM2CvdJ8sILL+T+++/P/fffn/79++d73/teo1+nDwAAAAAAAEBZXnHfgJdffrk27tKlyxZf17lz59r4lVdeadSca9as2WjeBQsW5DOf+Uwtzvfo0SPvfe978y//8i8b/YWBRx99NJ/61KeydOnSRs0HAAAAAAAAQFl20Ddg1apVtXH79u23+Lp27do1eI8t8Y9B/4ILLsgrr7ySnj175lvf+lYGDBiQSqWSJFm2bFn+67/+Kz/72c+SJM8++2y+8Y1v5LrrrmvUnM3pmWeeyXbb+fse8H/dmjVran/OnDmzlVcD8ObjOQrQNJ6jAE3nWQrQNJ6j8Naxbt26FrmvQN+A9Q/XJI2KznV1dbXx2rVrGzXn6tWrNzpetmxZdt5559x6663ZfffdN/qua9euufDCC9OtW7dce+21SZIHH3wwU6dOzfve975Gzdtc6uvrU19f3ypzA61jw2clAI3nOQrQNJ6jAE3nWQrQNJ6jwNYQ6BuwYWhvzN+M2DBQb+nv1q+3fnf8hr75zW++Ic5v6D/+4z9y7733Zvbs2UmSW265pdUCfV1dnR308Baw4X9wNvY5B4DnKEBTeY4CNJ1nKUDTeI7CW8e6detaZIOyQN+ADV9r35hX1W947vbbb9+oOTt06LDR8Q477JBjjz32n15TV1eXIUOG5Morr0ySPPbYY6lWqw3G/pa2zz77pHPnzsXnBcqaOXNm1qxZk7Zt2+aggw5q7eUAvOl4jgI0jecoQNN5lgI0jecovHUsX748s2bNavb72vLcgG7dutXGy5cv3+LrNjx3w3tsiU6dOm10fNBBB23RjvR3v/vdtfHSpUuzePHiRs0LAAAAAAAAQBkCfQN22WWX2njp0qVb/OqCDeN4jx49GjVnXV1dunTpUjveYYcdtui6HXfccaPjpUuXNmpeAAAAAAAAAMoQ6Bvw9re/vTaur6/PggULNnvN6tWrs3DhwtrxXnvt1eh599lnn9p42bJlW3TNP/7lgbq6ukbPCwAAAAAAAEDLE+gbsOeee6Zr16614y35bYGnn366FssrlUr222+/Rs+74TXPPffcFl2z4V8KqFQqG+3+BwAAAAAAAGDbIdA3oFKppG/fvrXjqVOnbvaaRx55pDbef//9t/gV9Rvq379/bTx79uzMnTt3s9dMnz69Nu7du3c6duzY6HkBAAAAAAAAaHkC/SYcc8wxtfHEiROzYsWKTZ5bX1+fcePG1Y4HDhy4VXN+6EMfSqdOnWrHo0eP/qfnr1q1KnfcccdG1wMAAAAAAACwbRLoN+HYY4+t7YJfunRpLrnkkk2ee80119R2u7dv3z5Dhw7dqjnbt2+fj33sY7XjsWPHZsqUKZs8//LLL8/zzz+fJGnbtm0+8YlPbNW8AAAAAAAAALQ8gX4TOnTokC9/+cu14wkTJuTcc8/N4sWLa58tX748I0aMyPXXX1/77IwzzkiPHj3ecL/HHnss+++/f+2fDXe+b+jLX/5ydt999yTJunXr8sUvfjH/3//3/2XlypW1c5YuXZoLLrggN998c+2zz33uc9lzzz23/l8YAAAAAAAAgBbVprUXsC371Kc+lccffzz33HNPkuTuu+/OfffdlwMOOCB1dXWZNWtWXn311dr5/fr1y5lnntmkOTt16pQf/vCH+fznP59FixZlzZo1+e53v5uRI0dmn332SZL86U9/yurVqzea9+yzz27SvAAAAAAAAAC0LDvo/4lKpZLvfve7+dSnPpVKpZIkWb16dWbOnJknnnhiozg/cODAXH/99WnTpul/5+GAAw7IzTffnL59+9Y+W7FiRWbMmJEZM2ZsFOdPOeWUXH/99WnXrl2T5wUAAAAAAACg5dhBvxlt2rTJ8OHDc8opp2TcuHF59NFHs3DhwqxduzY9evTIIYcckiFDhuTwww9v1nn32muv3HTTTXnwwQdzzz33ZMaMGXnxxRezdu3a7Lbbbnnve9+bj33sYznooIOadV4AAAAAAAAAWoZAv4X69OmTPn36bPX1/fr1y6xZsxp93YABAzJgwICtnhcAAAAAAACAbYNX3AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAQI9AAAAAAAAABQg0AMAAAAAAABAAcUC/erVq0tNBQAAAAAAAADbnGKB/v3vf38uvfTSzJw5s9SUAAAAAAAAALDNKBboX3755dxyyy35+Mc/nhNOOCE//vGP89JLL5WaHgAAAAAAAABaVfHfoK9Wq5k9e3a++93v5oMf/GC+8IUvZPLkyVmzZk3ppQAAAAAAAABAMcUC/ec///nssssuSV6P9Emydu3a/OpXv8rZZ5+d97///bnsssvyxz/+sdSSAAAAAAAAAKCYYoH+vPPOy0MPPZQbbrghgwcPTseOHZO8Huur1WqWLl2am266KUOHDs2JJ56YMWPGZNGiRaWWBwAAAAAAAAAtqugr7iuVSt73vvdlxIgReeSRR3LVVVflqKOOSps2bZL8b6x/5plncsUVV+Soo47KsGHDcv/992ft2rUllwoAAAAAAAAAzapNa028/fbb5/jjj8/xxx+fxYsXZ+LEibnrrrvyxz/+caNX4E+ZMiVTpkxJ9+7dc8IJJ2Tw4ME58MADW2vZAAAAAAAAALBViu6g35Qdd9wx//qv/5qxY8fm3nvvzRe+8IW87W1vS/K/u+qXLFmSG2+8MUOGDMlHP/rR/OQnP8nixYtbeeUAAAAAAAAAsGW2iUC/oXe84x0555xzMnny5EycODFf/epXc/DBB2e77barxfpZs2bl8ssvz1FHHZWzzz47U6dObe1lAwAAAAAAAMA/1WqvuN8S++yzT3r37p0+ffpk7Nix+cUvfpFKpVL7fs2aNZk8eXImT56cvffeO//xH/+RQYMGteKKAQAAAAAAAKBh22Sgf+211/LQQw/lgQceyK9+9assW7YsSWpxfv1v1G84nj17dr72ta9lwoQJGTFiRHbcccfyCwcAAAAAAACATdhmAv26devy61//OhMnTswDDzyQlStXJtk4xidJt27dMmjQoAwePDg77rhj7r777owfPz7PPfdckuRXv/pVzjjjjNx4443p2LFj8X8PAAAAAAAAAGhIqwf6J554InfffXcmTZqUJUuWJHljlG/Tpk2OPPLInHzyyfnQhz6Udu3a1b4788wzc+aZZ2by5Mm56KKL8vLLL+dPf/pTfvrTn2bYsGFF/10AAAAAAAAAYFNaJdDPnj07d911V37xi19k/vz5Sf43ym/4G/P77bdfBg8enBNPPDE777zzP73nMccck7q6unzxi19MkvziF78Q6AEAAAAAAADYZhQL9M8//3wmTpyYiRMnZtasWUkajvLdu3fP8ccfn1NOOSUHHnhgo+b40Ic+lE6dOmXFihWZN29e8y0eAAAAAAAAAJqoWKAfMGBAkoajfF1dXY466qgMHjw4H/zgB9OmzdYtq1KppFu3bnn11Vc3eg0+AAAAAAAAALS2YoG+Wq2mUqmkUqmkWq2mWq3mne98ZwYPHpwTTjghO+64Y5PnqK+vz6JFi1KtVrPffvs1w6oBAAAAAAAAoHkU/Q36arWanXbaKSeeeGIGDx6c/fffv1nvv2rVqlx11VV529velre//e3Nem8AAAAAAAAAaIpigf6YY47J4MGD84EPfCB1dXUtMkfHjh3z4Q9/uEXuDQAAAAAAAABNUSzQ/9d//VepqQAAAAAAAABgm7Nda008b968XHfddXnwwQc3ec6oUaMyaNCgXHnllfnb3/5WcHUAAAAAAAAA0LyKB/pVq1blW9/6Vo499thcc801eeSRRzZ57rx58zJnzpzccMMNOe644/L9738/69atK7haAAAAAAAAAGgexV5xnySvvvpqPv/5z2fGjBmpVqupVCqZO3fuJs+fP39+bbx27dpcf/31mTt3bq6++upst12rbf4HAAAAAAAAgEYrWrm//e1v5/e//33tuFqtpk2bTf8dgWOPPTYf+MAHUldXl0qlkmq1mvvuuy8jR44ssFoAAAAAAAAAaD7FAv2f//zn3HnnnbXQ/i//8i+5884788Mf/nCT1wwdOjSjRo3Kvffem759+yZ5Pepff/31WbhwYamlAwAAAAAAAECTFQv0d9xxR2184IEH5mc/+1ne+c53btG1vXr1yujRo3PggQcmef1197fffnuLrBMAAAAAAAAAWkKxQD99+vTa+IILLkiHDh0adX27du1y7rnn1o6nTp3abGsDAAAAAAAAgJZWLNDPmzcvSdKxY8fa6+obq1+/funQoUOq1WqeffbZ5lweAAAAAAAAALSoYoF+xYoVqVQq6dat21bfo66uLjvssEOS5JVXXmmupQEAAAAAAABAiysW6Nu3b59qtZolS5Y06T7Lli1LknTp0qU5lgUAAAAAAAAARRQL9G9729uSJK+99lpmzJixVff4y1/+kuXLl6dSqWSXXXZpzuUBAAAAAAAAQIsqFugPPfTQ2vi6667bqnuMHj26Nj7ssMOavCYAAAAAAAAAKKVYoD/++ONr44ceeigjR45s1PW33HJLxo8fXzv+yEc+0lxLAwAAAAAAAIAWVyzQH3LIIenbt2+SpFqt5gc/+EGGDRuW3/3ud//0uj/84Q/56le/mksvvTRJUqlU0rdv3/Tr16/F1wwAAAAAAAAAzaVNyckuueSSDB06NCtXrky1Ws2UKVMyZcqUdO3aNQcccEB22mmntG/fPq+99loWL16cp59+OkuWLEnyetRPkq5du+ayyy4ruWwAAAAAAAAAaLKigX7vvffOyJEjc9ZZZ2XZsmVJXg/vL7/8cqZNm/aG89dH+UqlkiTZYYcdcu211+btb397uUUDAAAAAAAAQDMo9or79fr375877rgjH/7wh7f4mkqlko985CMZP3583vOe97Tg6gAAAAAAAACgZRTdQb/ennvumWuvvTZ/+9vfMmnSpEyfPj2zZ8/OSy+9lNWrV6djx47p1q1bevfunfe85z059thj7ZoHAAAAAAAA4E2tVQL9er169cq///u/59///d9bcxkAAAAAAAAA0OKKv+IeAAAAAAAAAN6KBHoAAAAAAAAAKOBNGehfeOGFXHvtta29DAAAAAAAAADYYq3yG/QLFy7MAw88kL/+9a959dVXU19fn3Xr1jV47rp167J27dqsWrUqK1asyN///vc899xzSZIvfelLJZcNAAAAAAAAAFutaKCvVqu58sor87Of/Sz19fVbfY8kqVQqzbk0AAAAAAAAAGhRRQP9VVddlRtuuKF2vGFk/2fhff13AAAAAAAAAPBmVSzQP//88xkzZkwtwFer1Vp4r6urq73ivlKppFKpbLTDfsNo37t375x00kn58Ic/XGrpAAAAAAAAANBk25Wa6K677sratWtrx5/85Cdz77335sknn8yUKVNqn3/2s5/Nk08+mT/+8Y+5//77M2LEiOy+++61oP/888/nuOOOy957711q6QAAAAAAAADQZMUC/bRp02rjQYMGZfjw4XnHO96Rurq67Lzzztl3331TrVZrsb5NmzbZc889M3jw4EyYMCHve9/7kiSvvvpqhg8fXmrZAAAAAAAAANAsigX6OXPm1Mann376G77v06dPkuS5557LokWLNvquc+fOufrqq9OjR49Uq9U8+uij+d3vfteyCwYAAAAAAACAZlQs0L/yyitJku233z7vete73vD9fvvtVxv/8Y9/fMP3O+ywQz772c/WjidPntwCqwQAAAAAAACAllEs0K9cuTKVSiU77rhjKpXKG75/xzveURvPmjWrwXucdNJJtfFTTz3V/IsEAAAAAAAAgBZSLNB37tw51Wo11Wq1we979epVGz/77LMNnrPrrrumffv2SV5/FT4AAAAAAAAAvFkUC/TdunVLkixZsqTB7/fYY4/azvpNBfok6d69e6rVapYtW9b8iwQAAAAAAACAFlIs0O+7775JklWrVuXPf/7zG75v165devbsmWq1mqeffrrBnfbVajWLFi1KkqxZs6ZlFwwAAAAAAAAAzahYoO/bt29tPGrUqAbP2XvvvZO8/nv106dPf8P3f/jDH2phvkuXLi2wSgAAAAAAAABoGcUC/Yc//OHU1dUlSe69996cf/75td3w6x122GG18dVXX53Vq1fXjtetW5f/9//+X5KkUqnkHe94R4FVAwAAAAAAAEDzKBbo99xzzwwaNKj26vrx48dnwIABueGGG2rnHH/88dluu9eX9MQTT+TUU0/NmDFj8tOf/jRDhw7Nb3/729q5hx9+eKmlAwAAAAAAAECTtSk52Te/+c3MnDkzzz33XJLXf0d+w9+S79WrV0466aSMHz8+lUolTz/9dK644ookr//+fKVSSZK0b98+Q4cOLbl0AAAAAAAAAGiSYjvok6R79+75yU9+kqOOOqr2Wa9evTY658ILL8w+++yzUZBfP17/5/Dhw9OzZ8+SSwcAAAAAAACAJika6JNk1113zfXXX59bbrklp512Wvbbb7+Nvu/cuXNuvfXWfPSjH01dXV3tlfjVajW77bZbfvCDH+Tkk08uvWwAAAAAAAAAaJKir7jf0CGHHJJDDjmkwe86d+6cK664Iuedd16efPLJLF++PHvssUf69OlT+416AAAAAAAAAHgzKRboZ8+encceeyxHH330Fr+efqeddsoHPvCBFl4ZAAAAAAAAALS8YtvRx40bl29/+9v54Ac/mCFDhuQXv/hFqakBAAAAAAAAoNUV20H/m9/8pvZ78k899VQqlUqpqQEAAAAAAACg1RXbQT9//vyNony/fv1KTQ0AAAAAAAAAra5YoG/Xrt1Gx+3bty81NQAAAAAAAAC0umKB/qijjqq94j5Jfvvb35aaGgAAAAAAAABaXbFA/7WvfS177rln7XjEiBFZtGhRqekBAAAAAAAAoFUVC/Q777xzxo4dm+OPPz7VajV//etfc8IJJ+Taa6/N9OnTs3r16lJLAQAAAAAAAIDi2pSa6Oqrr06S7LHHHjnssMPy29/+NkuWLMl///d/57//+7+TJJ07d06XLl1SqVQ2e79KpZL777+/RdcMAAAAAAAAAM2lWKAfNWrURuF9/XjD36V/5ZVX8sorr/zT+1QqlVSr1S2K+AAAAAAAAACwrSgW6JONY3xr3gMAAAAAAAAASisW6AcPHlxqKgAAAAAAAADY5hQL9CNGjCg1FQAAAAAAAABsc7Zr7QUAAAAAAAAAwFuBQA8AAAAAAAAABQj0AAAAAAAAAFCAQA8AAAAAAAAABbQpNdHRRx/drPerVCq5//77m/WeAAAAAAAAANBSigX6+fPnp1KppFqtNuk+6+9RqVSaaWUAAAAAAAAA0PKKBfokWxXnNwzx1Wq1yYEfAAAAAAAAAFpDsUA/ePDgLT63vr4+r776ap5//vn85S9/yapVq1KpVNK5c+d861vfyi677NKCKwUAAAAAAACA5lcs0I8YMWKrrnvttddy66235gc/+EFWrFiR733ve7nxxhuz2267NfMKAQAAAAAAAKDlbNfaC9ic9u3b57TTTsuPfvSjtGnTJgsWLMj555/f2ssCAAAAAAAAgEbZ5gP9eoceemhOO+20VKvVPPbYY3nwwQdbe0kAAAAAAAAAsMXeNIE+ST75yU/WxnfddVcrrgQAAAAAAAAAGudNFeh33333dOnSJUny5JNPtvJqAAAAAAAAAGDLvakCfZK0a9cu1Wo1L7zwQmsvBQAAAAAAAAC22Jsq0C9ZsiSLFi1Kkmy//fatvBoAAAAAAAAA2HJvqkA/ZsyYJEmlUsluu+3WuosBAAAAAAAAgEZo09oL2BKrV6/OmDFjMmrUqFQqlSTJEUcc0cqrAgAAAAAAAIAtVyzQn3/++Y06v1qtZtWqVVmyZEmeeuqpvPLKK6lWq0mSNm3a5JRTTmmJZQIAAAAAAABAiygW6O+8887a7vfGqlarqVQqqVQqqVar+exnP5u99967mVcIAAAAAAAAAC2n+Cvu1++C35rrtttuu3z605/O17/+9WZeFQAAAAAAAAC0rGKBfvfdd2/0NXV1dWnfvn122WWXHHLIIRk0aFB69+7dAqsDAAAAAAAAgJZVLND/8pe/LDUVAAAAAAAAAGxztmvtBQAAAAAAAADAW8E2HehXrFiRdevWtfYyAAAAAAAAAKDJWi3QP/7447nooosyYcKETZ4zZsyYHHbYYTn77LPz+OOPF1wdAAAAAAAAADSvYr9Bv96iRYvyjW98Iw8//PDrC2jTJh/96EcbPHf+/PlZsWJFJk+enMmTJ+eEE07IpZdemg4dOpRcMgAAAAAAAAA0WdFAv2jRonz605/Oc889l2q1mkqlkueee26T58+fP782rlarmThxYv7+979n9OjR2X777UssGQAAAAAAAACaRdFX3H/zm9/M3Llza8dt27ZNr169Nnn+6aefnk9+8pPp2rVrktcj/fTp03PFFVe09FIBAAAAAAAAoFkVC/TTp0/PQw89lEqlkiQZMGBAHnjggVxyySWbvOaDH/xghg8fngceeCDHH398ktcj/a233rpR6AcAAAAAAACAbV2xQD9hwoTa+H3ve19GjhyZHj16bNG1nTt3zlVXXZX+/fsneT3S33777S2yTgAAAAAAAABoCcUC/RNPPFEbn3vuubWd9I3xla98pTZ+7LHHmmNZAAAAAAAAAFBEsUD//PPPJ0m6du2aAw88cKvucfDBB6dTp06pVquZN29ecy4PAAAAAAAAAFpUsUC/cuXKVCqVdOrUqUn36datW5JkxYoVzbEsAAAAAAAAACiiWKBfv/N90aJFqa+v3+r7LFmyJMn/hnoAAAAAAAAAeDMoFuj32muvJMnq1aszbdq0rbrHzJkzazvxd91112ZcHQAAAAAAAAC0rGKB/rDDDquNr7322q26x8iRI2vj/v37N3lNAAAAAAAAAFBKsUB/4okn1sa/+93vcvHFFzfqVfdXX311HnroodrxoEGDmnN5AAAAAAAAANCiigX6/fffP0cffXSq1WqS5Oc//3lOPfXU3H333Vm+fHmD17z66quZNGlSPvGJT+RHP/pRkqRSqeToo4/Ou971rlJLBwAAAAAAAIAma1NysosvvjgzZszIokWLkiR/+tOfct555yVJ9thjj+y0005p3759XnvttSxevDjz58+vBf31f+6222659NJLSy4bAAAAAAAAAJqsaKDv2bNnfvzjH2fYsGFZsGBBKpVKLbzPmzcv8+fPr527/vPk9V3zSbLXXntl5MiR2XHHHUsuGwAAAAAAAACarNgr7tfbb7/9MmHChHzuc59L+/btN/ruH3fLr9ehQ4ecdtppGTduXHr37l1srQAAAAAAAADQXIruoF+vS5cuOf/883PWWWdlypQpmT59embPnp2XXnopq1evTseOHdOtW7f07t0773nPe3LUUUelS5curbFUAAAAAAAAAGgWrRLo1+vUqVMGDRqUQYMGteYyAAAAAAAAAKDFFX/FfWOsWLEi69ata+1lAAAAAAAAAECTtVqgf/zxx3PRRRdlwoQJmzxnzJgxOeyww3L22Wfn8ccfL7g6AAAAAAAAAGhexV9xv2jRonzjG9/Iww8//PoC2rTJRz/60QbPnT9/flasWJHJkydn8uTJOeGEE3LppZemQ4cOJZcMAAAAAAAAAE1WNNAvWrQon/70p/Pcc8+lWq2mUqnkueee2+T58+fPr42r1WomTpyYv//97xk9enS23377EksGAAAAAAAAgGZR9BX33/zmNzN37tzacdu2bdOrV69Nnn/66afnk5/8ZLp27Zrk9Ug/ffr0XHHFFS29VAAAAAAAAABoVsUC/fTp0/PQQw+lUqkkSQYMGJAHHnggl1xyySav+eAHP5jhw4fngQceyPHHH5/k9Uh/6623bhT6AQAAAAAAAGBbVyzQT5gwoTZ+3/vel5EjR6ZHjx5bdG3nzp1z1VVXpX///klej/S33357i6wTAAAAAAAAAFpCsUD/xBNP1MbnnntubSd9Y3zlK1+pjR977LHmWBYAAAAAAAAAFFEs0D///PNJkq5du+bAAw/cqnscfPDB6dSpU6rVaubNm9ecywMAAAAAAACAFlUs0K9cuTKVSiWdOnVq0n26deuWJFmxYkVzLAsAAAAAAAAAiigW6NfvfF+0aFHq6+u3+j5LlixJ8r+hHgAAAAAAAADeDIoF+r322itJsnr16kybNm2r7jFz5szaTvxdd921GVcHAAAAAAAAAC2rWKA/7LDDauNrr712q+4xcuTI2rh///5NXhMAAAAAAAAAlFIs0J944om18e9+97tcfPHFjXrV/dVXX52HHnqodjxo0KDmXB4AAAAAAAAAtKhigX7//ffP0UcfnWq1miT5+c9/nlNPPTV33313li9f3uA1r776aiZNmpRPfOIT+dGPfpQkqVQqOfroo/Oud72r1NIBAAAAAAAAoMnalJzs4osvzowZM7Jo0aIkyZ/+9Kecd955SZI99tgjO+20U9q3b5/XXnstixcvzvz582tBf/2fu+22Wy699NKSywYAAAAAAACAJisa6Hv27Jkf//jHGTZsWBYsWJBKpVIL7/Pmzcv8+fNr567/PHl913yS7LXXXhk5cmR23HHHkssGAAAAAAAAgCYr9or79fbbb79MmDAhn/vc59K+ffuNvvvH3fLrdejQIaeddlrGjRuX3r17F1srAAAAAAAAADSXojvo1+vSpUvOP//8nHXWWZkyZUqmT5+e2bNn56WXXsrq1avTsWPHdOvWLb1798573vOeHHXUUenSpUtrLBUAAAAAAAAAmkWrBPr1OnXqlEGDBmXQoEGNum7hwoW5+eabc84557TQygAAAAAAAACgebVqoG+sqVOn5uabb86DDz6Y+vp6gR4AAAAAAACAN41tPtAvX74848ePz80335xnn302yeu/UV+pVFp5ZQAAAAAAAACw5bbZQP/MM8/kxhtvzF133ZWVK1emWq0miTAPAAAAAAAAwJvSNhXo6+vr8z//8z+56aab8vjjjyfJG8L8+uNDDz20dRYJAAAAAAAAAFthmwj0L774Ym677bbcfvvtefHFF5P872vsK5VKqtVqqtVqdt9995x88sk5+eST87a3va2VVw0AAAAAAAAAW65VA/3jjz+em266Kf/zP/+T+vr62u749arVajp27JiBAwdm8ODBee9739tKKwUAAAAAAACApike6FeuXJm77rorN910U/7yl78keeNu+Uqlkv79++fkk0/OMccckw4dOpReJgAAAAAAAAA0q2KB/tlnn83NN9+c8ePHZ/ny5Zv8bfn1brjhhlJLAwAAAAAAAIAW16KBvlqt5pe//GVuuummTJ06tfZZktpu+STp379/hg4dmquuuioLFixoySUBAAAAAAAAQKtokUC/ePHijB07Nrfeemv+/ve/J/nf19ivt9NOO+WUU07J0KFD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AAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQgEAPAAAAAAAAAAUI9AAAAAAAAABQQJvWXsCbxVNPPZVbbrkl06ZNy8KFC1OpVLLrrrvm0EMPzZAhQ3LooYc2+5wLFy7Mz3/+8zz22GOZM2dOXn755Wy//fbZeeedc+ihh+aEE07IEUcc0ezzAgAAAAAAAND8BPrNWLduXa688sqMGTMm1Wp1o+/mzJmTOXPmZOzYsTn11FNz4YUXpkOHDs0y53XXXZeRI0dmzZo1G323Zs2aLF++PHPnzs0dd9yR9773vbnqqquyyy67NHleAAAAAAAAAFqOV9xvxoUXXpgbbrihFuc7dOiQd7/73Tn44IM3ivFjx47NOeeck3Xr1jV5zosuuijXXHPNRnF+r732Sr9+/dKnT5+0a9eu9vm0adPysY99LC+88EKT5wUAAAAAAACg5Qj0/8T48eMzbty42vFnPvOZPPzww7n99ttz22235eGHH85pp51W+/7BBx/M6NGjmzTnuHHjMnbs2NrxkUcemXvvvTf33XdffvrTn2bs2LF59NFH88UvfjHbbff6/31///vf89WvfrVJ8wIAAAAAAADQsgT6TVi1alWuuuqq2vHHP/7xXHTRRencuXPts86dO+f888/PsGHDap+NGjUqy5Yt26o5165dm+9///u14w984AMZNWpUevfuvdF5nTp1yllnnZVLL7209tlvf/vbPPTQQ1s1LwAAAAAAAAAtT6DfhEmTJtVeG9+5c+ecd955mzz3rLPOqkX0ZcuWbbTrvjEeffTR2px1dXUZPnx46urqNnn+0KFDc8ghh9SO77nnnq2aFwAAAAAAAICWJ9BvwqRJk2rjgQMHbrRz/h/V1dVlyJAhDV7bGI899lhtfNBBB2XPPffc7DUDBgyojZ988smtmhcAAAAAAACAlifQN6BarWbatGm14yOOOGKz1xx++OG18YwZM7J48eJGz/viiy/Wflf+H19rvyndu3evjZcsWdLoOQEAAAAAAAAoo01rL2BbNG/evCxfvrx2/M53vnOz1+y7776pq6tLfX19qtVqnnrqqRx55JGNmvfyyy/Pt7/97bzwwgupVCpbdM38+fNr4y5dujRqPgAAAAAAAADKsYO+AXPnzq2NK5VKevXqtdlr2rZtm549e9aO//rXv27V3G3bts0ee+yR3XfffbPnVqvV3H///bXjvffee6vmBAAAAAAAAKDlCfQNeOmll2rj7t27p23btlt03U477VQbv/jii82+rn907733Zvbs2bXjDX+PHgAAAAAAAIBti0DfgJdffrk2bsxr4zt37lwbv/LKK826pn/04osv5jvf+U7tuEePHjnhhBNadE4AAAAAAAAAtp7foG/AqlWrauP27dtv8XXt2rVr8B7NbeXKlfnSl7600S79s88+Ox06dGixOTfnmWeeyXbb+fse8H/dmjVran/OnDmzlVcD8ObjOQrQNJ6jAE3nWQrQNJ6j8Naxbt26FrmvQN+A9Q/XJI2KznV1dbXx2rVrm3VN661evTpf+tKX8vvf/7722XHHHZehQ4e2yHxbqr6+PvX19a26BqCsDZ+VADSe5yhA03iOAjSdZylA03iOAltDoG/AhqG9MX8zYsNAvaW/W98YK1asyBe/+MVMnTq19tkBBxyQyy67rNnnaqy6ujo76OEtYMP/4GyJ5xzA/3WeowBN4zkK0HSepQBN4zkKbx3r1q1rkQ3KAn0DNnytfWNeVb/hudtvv32zrmnx4sUZNmxYZsyYUfusd+/eGT16dDp37tysc22NffbZZ5tYB9CyZs6cmTVr1qRt27Y56KCDWns5AG86nqMATeM5CtB0nqUATeM5Cm8dy5cvz6xZs5r9vrY8N6Bbt2618fLly7f4ug3P3fAeTfXss8/mYx/72EZxft99981Pf/rT7Lzzzs02DwAAAAAAAAAtR6BvwC677FIbL126dItfXbB48eLauEePHs2ylscffzyf+MQn8re//a322UEHHZQbb7yx2eYAAAAAAAAAoOUJ9A14+9vfXhvX19dnwYIFm71m9erVWbhwYe14r732avI67r///px++ulZunRp7bP3v//9+clPfpLu3bs3+f4AAAAAAAAAlCPQN2DPPfdM165da8db8tsCTz/9dG2nfaVSyX777dekNdxzzz0566yzsnr16tpnp5xySq677rp07NixSfcGAAAAAAAAoDyBvgGVSiV9+/atHU+dOnWz1zzyyCO18f77758ddthhq+d/6KGH8p//+Z8bvVp/2LBhGTFiRNq0abPV9wUAAAAAAACg9Qj0m3DMMcfUxhMnTsyKFSs2eW59fX3GjRtXOx44cOBWzzt37tycc845Wbt2bZLX/7LABRdckHPOOWer7wkAAAAAAABA6xPoN+HYY4+t7YJfunRpLrnkkk2ee80112Tu3LlJkvbt22fo0KFbNefatWtz7rnn5tVXX6199vWvfz2f+9zntup+AAAAAAAAAGw7BPpN6NChQ7785S/XjidMmJBzzz03ixcvrn22fPnyjBgxItdff33tszPOOCM9evR4w/0ee+yx7L///rV/7rjjjjecc+edd+YPf/hD7fjEE0/M6aef3lz/SgAAAAAAAAC0Ij9o/k986lOfyuOPP5577rknSXL33XfnvvvuywEHHJC6urrMmjVro93u/fr1y5lnnrlVc1Wr1fzoRz/a6LN58+bl3/7t3xp1n9GjR2/V/AAAAAAAAAC0LIH+n6hUKvnud7+b7t2755Zbbkm1Ws3q1aszc+bMN5w7cODAXHHFFWnTZuv+J501a1aee+65jT574okntupeAAAAAAAAAGx7BPrNaNOmTYYPH55TTjkl48aNy6OPPpqFCxdm7dq16dGjRw455JAMGTIkhx9+eJPmefbZZ5tpxQAAAAAAAABsiwT6LdSnT5/06dNnq6/v169fZs2atcnvjzvuuBx33HFbfX8AAAAAAAAAtm3btfYCAAAAAAAAAOCtQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAAAAAAgAIEegAAAAAAAAAoQKAHAAAA/v/27jvKquruH/9nmKHOAEOTHsVC8cmyfdXYkhhiLNEEA8aGJGrsUbHFgtizBFFjLFHRKC7FWAKKDVGDJY+KItEn9sGoKEVpI2XAUIb7+8PF+c3FKXeG4SCX12stV84+d5+9952s9VmX+75nHwAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSULSxF7CpeP/99+OBBx6IqVOnxty5c6OgoCC6dOkSu+yySwwaNCh22WWXRp/z66+/jkceeSSeffbZKCsri4qKimjXrl307NkzDjrooBgwYEC0adOm0ecFAAAAAAAAoPEJ6OuwZs2aGDVqVNxzzz2RyWSyXvvkk0/ik08+iXHjxsVhhx0Ww4cPj5YtWzbKvO+//34MHTo0Pv/886zz8+bNi3nz5sW//vWvuPPOO2PUqFGxxx57NMqcAAAAAAAAAGw4trivw/Dhw2PMmDFJON+yZcvYcccdY6eddsoK48eNGxdnn312rFmzZr3nLCsri9/85jdZ4XzPnj1j9913j549eybn5s6dGyeccEK8+eab6z0nAAAAAAAAABuWgL4WEyZMiPHjxyftY445Jl5++eV4+OGH46GHHoqXX345jj322OT1F154Ie666671mnPlypVx1llnxdKlSyMiolu3bnHffffFP/7xj+R/x44dGz169IiIiFWrVsUZZ5wRFRUV6zUvAAAAAAAAABuWgL4GK1asiOuvvz5pH3HEEXHJJZdESUlJcq6kpCQuuuiiOOWUU5Jzd9xxRyxZsqTB8z744IPxySefREREcXFx3H333bH77rtn9dltt91i7Nix0alTp4iIWLBgQYwZM6bBcwIAAAAAAACw4QnoazBp0qSYN29eRHwTxJ9//vk19j3zzDNj6623joiIJUuWZN11Xx+ZTCbuv//+pH388cdHr169qu3btWvXuOCCC5L22LFjY/Xq1Q2aFwAAAAAAAIANT0Bfg0mTJiXHBxxwQNad8+sqLCyMQYMGVXttfXzwwQcxY8aMpD1w4MBa+x944IHRunXriIhYtGhRTJkypUHzAgAAAAAAALDhCeirkclkYurUqUl77733rvOavfbaKzn+97//HeXl5fWe97XXXkuOe/XqFd26dau1f9OmTWO33XZL2i+99FK95wQAAAAAAAAgHQL6asyaNSsqKiqSdr9+/eq8ZrvttovCwsKI+Cbgf//99+s9b1lZWXK8/fbb53RN3759k+N333233nMCAAAAAAAAkA4BfTWqbjNfUFAQPXv2rPOapk2bRufOnZP2559/vl7z5jJnRESPHj3Wa04AAAAAAAAA0iGgr8aCBQuS49LS0mjatGlO13Xo0CE5nj9/fr3nrXrNFltskdM1HTt2TI7Ly8ujsrKy3vMCAAAAAAAAsOEJ6KuxePHi5Lh169Y5X1dSUpIcL126dL3mrTpWbYqLi5PjTCbToHkBAAAAAAAA2PCKNvYCvotWrFiRHLdo0SLn65o1a1btGBty3qpzNnTehlj3Tv3ly5enMi+wca1Zsyb534qKio28GoBNjzoKsH7UUYD1p5YCrB91FDYf6+afjbWTuYC+GqtWrUqOmzTJfZOBwsLC5Hj16tX1nrfqNVXHqk1RUfb/hWltcb/uDwFmzpyZyrzAd0NlZWWUlZVt7GUAbLLUUYD1o44CrD+1FGD9qKOw+WmsG6VtcV+NquH42l9C5aJqOJ7rc+trmjfXoH3dHwI0ZF4AAAAAAAAANjwBfTWqbi9fn19CVO3bvHnzes9b9Zpc5125cmWNYwAAAAAAAADw3WGL+2q0bds2Oa7P80Oq9q06Rq5KS0tj2bJl9Zq3ar/CwsJo3bp1vedtiNLS0qx28+bNc96WHwAAAAAAAOC7rLKyMuum6nXz0YYS0Fdjiy22SI4XLVoUlZWVOYXP5eXlyXGnTp0aNO/s2bMjImLhwoU5XVO1X/v27aOgoKDe8zZEs2bNsv5OAAAAAAAAANTOFvfV2HLLLZPjysrKmDNnTp3XrFy5MubOnZu0t9pqq/Wad9asWTldM3PmzOS4V69e9Z4TAAAAAAAAgHQI6KvRo0ePaNOmTdIuKyur85rp06dHZWVlREQUFBRE79696z1vv379kuMPP/wwp2uq9uvTp0+95wQAAAAAAAAgHQL6ahQUFMSuu+6atKdMmVLnNa+++mpy3KdPn2jXrl295919992T4+nTp9e5zf2qVavijTfeSNp77LFHvecEAAAAAAAAIB0C+hrsv//+yfGTTz4Zy5Ytq7FvZWVljB8/PmkfcMABDZqzX79+0aNHj4iIWLNmTYwbN67W/k899VRUVFRERERJSUnsvffeDZoXAAAAAAAAgA1PQF+DAw88MLkLftGiRXHFFVfU2PfGG2+MGTNmREREixYt4te//nWD5iwoKIgjjzwyad9+++01bnU/Z86cuPbaa5P2oEGDomXLlg2aFwAAAAAAAIANT0Bfg5YtW8YZZ5yRtB977LE477zzory8PDlXUVERI0aMiNGjRyfnTjjhhOjUqdO3xnv99dejT58+yX+PPPJItfMOHjw4unfvHhERy5cvj+OOOy4mT56c1WfatGkxZMiQWLBgQURElJaWximnnNLwNwsAAAAAAADABle0sRfwXXb00UfHtGnTYuLEiRER8cQTT8QzzzwTffv2jcLCwigrK4vly5cn/X/wgx/Eqaeeul5ztmrVKm644YY47rjjYtmyZVFeXh6nnXZadOvWLXr06BFz586Nzz77LOnftGnTuO6666J9+/brNS8AAAAAAAAAG5Y76GtRUFAQ1157bRx99NFRUFAQERErV66Mt99+O956662scP6AAw6I0aNHR1HR+v/mYccdd4y77roreR59xDdb2k+dOjUrnC8tLY2//OUv8cMf/nC95wQAAAAAAABgw3IHfR2Kiorisssui4EDB8b48ePjtddei7lz58bq1aujU6dOsfPOO8egQYNir732atR5d95553jqqadi/Pjx8eyzz8bHH38cixYtipYtW8bWW28d++67bxxxxBHunAcAAAAAAADYRBRkMpnMxl4EAAAAAAAAAOQ7W9wDAAAAAAAAQAoE9AAAAAAAAACQAgE9AAAAAAAAAKRAQA8AAAAAAAAAKRDQAwAAAAAAAEAKBPQAAAAAAAAAkAIBPQAAAAAAAACkQEAPAAAAAAAAACkQ0AMAAAAAAABACgT0AAAAAAAAAJACAT0AAAAAAAAApEBADwAAAAAAAAApKNrYCwBgw1q8eHE89NBD8cILL8THH38cy5cvj44dO0avXr3ikEMOiYMPPjhatGixQeaeOnVq/P3vf48333wz5s+fH82aNYsuXbrEHnvsEYcddlj07du3Uea5+OKLY9y4cRERMWLEiBg4cGCjjAsQkV919L333otHH300/vWvf8WcOXOioqIiSkpKonv37rH77rvHr3/969hmm202yHsB8tP7778fDzzwQEydOjXmzp0bBQUF0aVLl9hll11i0KBBscsuuzT6nF9//XU88sgj8eyzz0ZZWVlUVFREu3btomfPnnHQQQfFgAEDok2bNvUaM63PrQDryoc6umrVqpg4cWI8//zz8e6770Z5eXmsXr06SktLo0+fPvHjH/84Bg4cGMXFxY3+XgAi8qOW1mTRokVx8MEHx4IFCyIioqysbL3HBDa+gkwmk9nYiwBgw3jllVfi/PPPTz7AVWebbbaJP/3pT436peOKFSvi4osvjieeeKLGPk2aNImTTjopzjzzzCgsLGzwXK+++mocd9xxSVtADzSmfKmjS5YsiUsvvTSefvrpWvs1adIkjjzyyLjooouiWbNmDVo7sHlYs2ZNjBo1Ku65556o7WuFww47LIYPHx4tW7ZslHnff//9GDp0aHz++ec19uncuXOMGjUq9thjjzrHS/NzK0BV+VJH33zzzfjDH/4Qs2bNqrVfu3bt4uqrr47+/fvXe80ANcmXWlqb8847L+uzqoAe8oOAHiBPvfrqq3HSSSfFqlWrknPbbLNNdOjQIT7//PP48ssvk/Nt27aNhx9+OLbaaqv1nreysjJOPPHEeOWVV5JzrVu3ju222y5WrlwZZWVlWWsaPHhwXHrppQ2aa/ny5XHIIYfE7Nmzk3MCeqCx5EsdraioiGOOOSY++OCD5FxRUVFst9120bZt21i4cGH85z//yfoyY5999ok77rhDEAXUaNiwYTF+/Pik3bJly+jdu3cUFBREWVlZfP3118lrP/nJT+LWW2+NJk3W7yl7ZWVlMXjw4Fi6dGlyrmfPntG1a9f44osvYubMmcn5pk2bxr333lvr3VJpfm4FWFc+1NEpU6bEiSeemFUrS0tLY+utt47CwsKYMWNGzJ8/P3mtoKAgRo4cGYceeuh6vQ+AtfKhltbmxRdfjJNPPvlb8wObPgE9QB5atGhRHHTQQVFeXh4REb17945rr702ubszk8nE5MmTY/jw4fHVV18lfSZMmLDeYcxf/vKXuOmmmyLim398Dx06NI4//vho3rx5REQsXLgwrr766njyySeTa2644Yb4+c9/Xu+5rrrqqhg7dmzWOQE90BjyqY5ecMEFMWHChKT929/+Nk477bQoLS1Nzs2ZMydGjhwZzzzzTHLutNNOi6FDh67XewHy04QJE+KCCy5I2sccc0ycffbZUVJSEhHf/DDo5ptvjnvuuSfpc95558WJJ57Y4DlXrlwZAwYMiE8++SQiIrp16xbXXHNN7L777kmfN954Iy688MLkLs6OHTvGM888k6xrXWl+bgWoKh/q6KJFi2L//fePxYsXR0RE+/bt47LLLov9998/K/z65z//GZdddlnMmTMnIiKaNWsWEyZM8FglYL3lQy2tTUVFRRx88MFZNwdECOghX6zfT4UA+E667bbbklCpS5cucc8992RtvVxQUBD77bdfjBkzJlq1ahUREdOnT4/HHntsveadP39+3HnnnUn77LPPjlNPPTX5kjMiokOHDnH99dfHL3/5y+Tcn//851i9enW95po2bVrcf//967VegJrkSx396KOPstZ0zjnnxLBhw7LC+YhvvlS46aabYsCAAcm5MWPGJH8DgLVWrFgR119/fdI+4ogj4pJLLsn6wrGkpCQuuuiiOOWUU5Jzd9xxRyxZsqTB8z744IPJF6HFxcVx9913Z30RGhGx2267xdixY6NTp04REbFgwYIYM2ZMteOl+bkVoKp8qaN33HFHEs4XFxfH/fffHwceeOC37kz90Y9+FA888EAy5sqVK+PGG29s8PsAiMifWlqbkSNHfiucB/KHgB4gz3z99dcxbty4pH3WWWdFhw4dqu3br1+/rG2SGvJhsaq///3vydZR3/ve9+KEE06ose9ll12WBESfffZZPP/88znPs/ZZoZlMJoqKihrt+VEAEflVR5944olk6/qtttqqzjsFhg0bltTUr7/+ul61Gdg8TJo0KebNmxcR33zpef7559fY98wzz4ytt946IiKWLFmStf1ofWQymawfZh5//PHRq1evavt27do1606qsWPHVhuop/W5FWBd+VBHM5lM1u4iJ5xwQrLO6nTp0iVOP/30pP3iiy9mbTsNUF/5UEtrM2XKlPj73/8eEd88ggnIPwJ6gDzz8ssvR0VFRUREtGrVqs4tOA877LAoKCiIiG/u/vz0008bPPekSZOS40MPPbTWbZ5LSkqy1lb12rrceOONMWPGjIj45ouA9u3b13+xADXIpzr6+uuvJ8fV3dG0rtLS0vh//+//Je333nsvp3UDm4+qteaAAw6odavOwsLCGDRoULXX1scHH3yQfPaLiDofZ3TggQcmX2QuWrQopkyZ8q0+aX1uBVhXPtTRTz/9NObOnZu0c3n0R//+/ZPjFStWxEcffZTL0gGqlQ+1tCbLly+P4cOHR8Q3z7A/++yzG7Re4LtNQA+QZ1577bXkeJdddsnaprM6HTt2jN69eyftF198sUHzlpeXx/Tp05P23nvvXec1e+21V3L8z3/+M7nLszbvvPNO8uyoXr16xe9///v6LxagFvlURxcsWJAc1/TL/nVV3f7+q6++yukaYPOQyWRi6tSpSbu+derf//53gx6dUbUu9+rVK7p161Zr/6ZNm8Zuu+2WtF966aWs19P63Aqwrnypo3PmzEk+IxcWFsaWW25Z5xrWfcSSz5lAQ+VLLa3Jn/70p+T59aecckpsu+229V4r8N0noAfIM2VlZcnx9ttvn9M1VZ+r/O677zZo3unTpydfVDZp0iRrzFzmXbp0adavUKuzatWqGDZsWFRWVkZBQUH88Y9/jGbNmjVovQA1yac6Onny5Pi///u/mDRpUvzkJz/JaR2zZ89Ojtu0aZPTNcDmYdasWckOIxHfPOajLtttt11yd3omk4n333+/3vM2dl1O43MrQHXypY7us88+8fbbb8eUKVPi0UcfTXaTqk3Vz5gRPmcCDZcvtbQ6b775ZrKN/nbbbRcnnXRSPVcJbCoE9AB5puqXhd/73vdyuqZHjx7J8eeff77e83bq1ClatGhR5zXdunXL2m65rrlvu+225G6no446KnbdddcGrRWgNvlWR1u2bBm9evWKtm3b1jnel19+GW+//XbSru1ZosDmp2qdKigoiJ49e9Z5TdOmTaNz585JuyE1suq8ucwZUXtdTuNzK0B18qWOrtW+ffvo06dPTuM999xzyXGTJk1iq622yuk6gHXlWy1da8WKFTFs2LBYs2ZNNGnSxI1JkOcE9AB5ZM2aNVlbNHXq1Cmn6zp06JAcz58/v0FzV91GOdd5CwsLs7a5q23uDz/8MO64446IiOjatWuce+65DVonQG3yuY7m4vbbb4/KysqkXfVZoQBV61RpaWk0bdo0p+vWt0ZWvWaLLbbI6ZqOHTsmx+Xl5Vm17btQb4HNU77U0fqqqKiIe++9N2nvvPPO0a5duwaPB2ze8rWW3nzzzfHpp59GRMQxxxwTO+20U73XCGw6BPQAeWTp0qVZH/RKSkpyuq5qvyVLljRo7kWLFiXHrVu3zvm6qnMvXbq02j6VlZVx8cUXx6pVqyIi4vLLL8/5vQHUR77W0VxMmTIlHnrooaTdv3//nHcQADYPixcvTo7TrFNV5821LhcXFyfHmUwma96NXW+BzVe+1NH6+uMf/5gVbB133HENHgsgH2vpu+++G3fffXdERHTv3j3OPvvseq8P2LQUbewFAGzudt111/X+gm/EiBExcODAWLFiRdb5XLbrjIis7ZJWrlzZoDVUvS7Xedede931r3XXXXclz2k65JBDYt99923QGoH8pI7WXUfrMmPGjDjrrLNizZo1yZh2KgHWVbXGpFmnGjLvutuBVh1jY9ZbYPOWL3W0Pu6555549NFHk/auu+4aP/vZzxo0FkBE/tXSVatWxbBhw5KbBa688spo1apVvdcHbFrcQQ+QR1avXp3VLiwszOm6oqL///da646Rq7V3t0dE1vM561J1jdXN/cknn8Qtt9wSERHt2rWLiy++uEHrA8hFPtbRusyePTuOO+64rDtKL7zwwth2223rPRaQ3zZWnap6TUPqckRk7Y6ysd4HQL7U0VyNGzcuRo4cmbRLS0vjuuuuq/c4AFXlWy0dPXp0lJWVRUTEr371q9hnn33qvTZg0yOgB8gj6344zPUf0FU/YOb63Kba5l57B2Yuqq5x3V+VrlmzJi6++OLk16XDhg2L9u3bN2h9ALnItzpal08//TQGDx4cc+bMSc4NGjQoBg8eXK9xgM1DY9SphtTIqvM2pC6vO+/GqLcAEflTR3Nx//33x/DhwyOTySTX33DDDdG1a9d6jQOwrnyqpdOnT4/bb789IiI6dOgQF154Yb3XBWyabHEPsJG9+uqryT9YG2rtrzGbN2+edT7X7Zqq9lt3jFxV3dqpPttEVe277hedY8eOjTfffDMiIn70ox/FL3/5ywatDchv6mjNdbQ277zzTpx88smxcOHC5NwBBxwQV155Zc5jAJuXxqhTDamRzZs3T77czHXedR83UnXetOstwFr5Ukfrcsstt8TNN9+ctIuKiuL666+PvfbaK+cxAGqSL7W0srIyLrroomRHgOHDh0dpaWm91wVsmgT0ABtZY36516ZNm2jSpEny69GKioqcrlu2bFly3LZt2wbNXfW6XOddt2/VD6EzZ86MG264ISIiWrVqFVdccUWD1gXkP3W0+jpam8mTJ8e5554bX3/9dXLu4IMPjlGjRn1rCz6AtRqjTjWkRpaWliZ1Ntd5q/YrLCyM1q1bV7uGDV1vAarKlzpak1WrVsWll14ajzzySHKuadOmcf3118cBBxxQz1UDVC9faundd98d7777bkRE9O/fP37+85/Xe03ApssW9wB5pEmTJtGhQ4ekXfWuyNpU7depU6cGzb3FFlvUe97Vq1fH4sWLk3bHjh2T40suuSSWL18eERHnnntudOvWrUHrAqiPfKqjNRk7dmycfvrpWeH84YcfHtddd51wHqhV1Tq1aNGinLf2LC8vT44bUiMbUh+r9mvfvn0U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ZwwaNCi22GKLeo27bNmyeOSRR2Ly5Mnxn//8JxYtWhSlpaXRtWvX2HfffePQQw+N7t2712tMAAAANn0FmUwms7EXAQAAADS+/v37x+zZsyMionv37vH88883+hzrBvT7779/DB06NN5+++0arykpKYkLLrggDj/88DrHr6ysjNGjR8edd94Zy5cvr7Vv69at46STTooTTzwxCgoK6hz7xRdfjCuvvDL5G9WkRYsWceaZZ8bvfve7b702a9as+OlPf5q0R4wYEW3atInLL7885s+fX+OYzZs3j/PPPz+OOeaYOtcJAABA/nAHPQAAANAoFi9eHMcdd1zMmDEjOde2bdto1qxZLFiwINbeI1BRURGXXHJJzJo1K84555wax1uxYkWceOKJ8frrr2edb9KkSXIHfnl5eaxZsyYiIpYuXRrXX399vPXWW3HDDTdEixYtahz7r3/9a1x77bXfOt+6desoKSmJBQsWxKpVqyIi4r///W+MGjUqvvjiixg+fHitf4MJEybEG2+8kawpIqJDhw4REbFw4cKs93bVVVdFYWFhHHXUUbWOCQAAQP7wDHoAAACgUdx5551JON+/f/947LHHYurUqfHyyy/Hyy+/HKeeemo0bdo06T969OiYOHFitWNlMpkYOnRoVjjfsWPHuPzyy+O1116LV155JV555ZWYMmVKXHrppVlb5j///PNxySWX1LjO5557LiucLyoqit/+9rfxzDPPxLRp0+LFF1+MN998M6655pqsce+777546qmnav0bvP7667FmzZro2LFjDB8+PN5444149dVX49VXX42XXnopjjjiiKz+o0aNivLy8lrHBAAAIH8I6AEAAIBGsfaO85NPPjluu+226Nu3b/Jax44d46yzzopbb701K6QfMWJErFix4ltjTZw4MV544YWk3bt375gwYUIcddRR0bZt2+R8aWlpDB48OB599NHYZpttkvOPP/54teH/f//737jqqquSdrNmzWL06NExbNiw2GqrrbLOH3roofG3v/0tWrdunZy/8cYbs+6Or862224bjzzySAwZMiTatGmTnO/SpUtceeWVcfTRRyfnli9fvkEePQAAAMB3k4AeAAAANgOzZ8+OPn36NPi/IUOG5DTPPvvsU+u29T/60Y/itNNOS9rz5s371l3pmUwmbrrppqTdqlWruPXWW6NTp041jtulS5e45ZZbsra1v/XWW5Nt9dd68sknY+7cuUn7zDPPjH322afGcXv16hWnn3560v7ss8/izTffrLF/kyZN4pprronOnTvX2OeUU06JgoKCpP3+++/X2BcAAID8IqAHAAAAGs25555bZ5/f/va30apVq6T99NNPZ71eVlaW9Rz7ww47LHr27FnnuFtvvXX86le/StofffRRfPDBB1l9Jk2alBwXFxfH4MGD6xx3wIAB0bt37/jZz34WJ5xwQpSUlNTYd9ddd43vf//7tY7XuXPn6NGjR9L+8ssv61wDAAAA+aFoYy8AAAAA2PCKioqiW7duDb5+iy22qLPPNttsE9tvv32d/YqLi2PPPfeMyZMnR0TEtGnTYs2aNdGkyTf3EUyZMiWr/8EHH5zzOg855JB44IEHkvbrr7+erCmTycS//vWv5LU999wz64cCNWnXrl088cQTOc2/44475tSvY8eOMXPmzIiI+Prrr3O6BgAAgE2fgB4AAAA2A507d47nnntug86RazgdEbH99tsnAf3y5cvjiy++iO7du0dExKeffpr0KywszCn0X+v73/9+NGnSJHlO/CeffJK89uWXX8by5cuTdr9+/XIeN1ddu3bNqV/Tpk2T49WrVzf6OgAAAPhussU9AAAA0ChyDacjItq3b5/VXrhwYXL81VdfJcdt2rSJZs2a5TxuixYtsragX7RoUXI8f/78WtfQGFq0aNHoYwIAAJA/BPQAAABAoyguLs65b8uWLbPaK1euTI4rKiqS41y2oK9t7Krbx1edo7o1NIaCgoJGHxMAAID8IaAHAAAAGsW6AXhtli1bltWuGu5XDeWrbknfkLGrhvDr/oDAs98BAABIm4AeAAAAaBRVt5Ovy7rbzXfu3Dk5Li0tTY6XLFkSK1asyHncioqKrIC+6jb2bdu2zepbXl6e87gAAADQGIo29gIAAACA/PDhhx/m3Pe9995Ljjt16pQVpG+33XbJcWVlZbz33nuxyy675DTuu+++G5lMJmlvueWWyXHnzp2juLg4CfCnT5+e83ovu+yymDt3bvTo0SN22mmnOOSQQ3K+FgAAANZyBz0AAADQKN56661YvHhxnf0WL14cU6dOTdp777131uu77bZbVnvixIk5r+Gpp57Kau+6667JcWFhYey0005J+7XXXstpW/6VK1fGxIkT44UXXoj77rsva+0AAABQHwJ6AAAAoFGsWLEi7r333jr7/fWvf83atn7AgAFZr2+//faxzTbbJO3x48fH559/Xue4H3/8cTz++ONJu0ePHvH9738/q89BBx2UHC9evDjGjRtX57hPP/10LFmyJGnvu+++dV4DAAAA1RHQAwAAAI1m9OjR8c9//rPG15977rm46667kvZOO+0Ue+21V1afgoKCOOmkk5L28uXL4/TTT48FCxbUOO7cuXPjjDPOiP/+97/JuZNOOimaNMn+6mPAgAHRqVOnpH3dddfF22+/XeO4s2bNimuvvTZp9+zZU0APAABAgwnoAQAAgEazatWqOO200+JPf/pTzJ07Nzk/Z86cGDFiRAwdOjQqKysjIqJ58+ZxxRVXVDvOgAEDYr/99kvaZWVlceihh8aDDz6YtY3+4sWL429/+1v86le/io8//jg5/8Mf/jAOP/zwb43brFmzuPrqq6OgoCAiIpYtWxa/+c1v4i9/+UvWepcvXx7jx4+Pww8/PObPn5+cv+yyy74V+gMAAECuCjKZTGZjLwIAAABofP3794/Zs2dHRERRUVF069ZtvcccMmRI/OY3v8lqr30me9euXaOioiKWLl0aEd/cCd+hQ4fIZDKxcOHCrHGaNm0aN954Y/z0pz+tca6Kior4/e9/H6+99lrW+SZNmkSHDh0iImLhwoWxZs2arNf33HPPuOWWW6KkpKTGse+77764+uqrs64tKCiIdu3aRbNmzWLBggWxevXqrGsuuuiiOPbYY7POzZo1K+s9jBgxIgYOHFjjvGtV/bvtvvvucd9999V5DQAAAJu+oo29AAAAAGDDW716dU7Pca9L1bvX19WzZ8/4wx/+EOecc07MnDkzMplMtdvS9+7dO0aMGPGt58Ovq6SkJO6666645ZZb4p577omvv/46IiLWrFmTdVf7WsXFxXHKKafE8ccfH0VFtX/lMWTIkPje974XV111VcycOTMiIjKZTJSXl3+rb7t27eLyyy+PAw88sNYxAQAAoC4CegAAAKDR7LDDDvHEE0/Eww8/HBMnTowZM2bEsmXLomPHjrHDDjvEIYccEvvtt1/O28QXFRXFWWedFUOGDInHH388Xnnllfj444+jvLw8Kisro0OHDtG3b9/40Y9+FL/4xS+iTZs2Oa/1xz/+cey1117x9NNPx0svvRTvvPNOLFiwIFauXBmlpaXRr1+/2HfffePQQw+N4uLihv5JAAAAIGGLewAAAKDBbNUOAAAAucvt5+oAAAAAAAAAwHoR0AMAAAAAAABACgT0AAAAAAAAAJACAT0AAAAAAAAApEBADwAAAAAAAAApENADAAAAAAAAQAoE9AAAAAAAAACQgoJMJpPZ2IsAAAAAAAAAgHznDnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAUCOgBAAAAAAAAIAUCegAAAAAAAABIgYAeAAAAAAAAAFIgoAcAAAAAAACAFAjoAQAAAAAAACAFAnoAAAAAAAAASIGAHgAAAAAAAABSIKAHAAAAAAAAgBQI6AEAAAAAAAAgBQJ6AAAAAAAAAEiBgB4AAAAAAAAAUiCgBwAAAAAAAIAU/H8WmDSe9o+P1wAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1200x800 with 1 Axes>"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 712,
       "width": 1012
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot([i.cpu() for i in history['train_acc']], label='train accuracy')\n",
    "plt.plot([i.cpu() for i in history['val_acc']], label='validation accuracy')\n",
    "\n",
    "plt.title('Training history')\n",
    "plt.ylabel('Accuracy')\n",
    "plt.xlabel('Epoch')\n",
    "plt.legend()\n",
    "plt.ylim([0, 1]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "YYMhWiIrBrV4",
    "is_executing": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Some weights of BertModel were not initialized from the model checkpoint at ../ROBERT_4_model.bin and are newly initialized: ['bert.pooler.dense.weight', 'bert.pooler.dense.bias']\n",
      "You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n",
      "C:\\root\\repos\\PycharmProjects\\stock-predict\\venv\\Lib\\site-packages\\torch\\nn\\modules\\transformer.py:282: UserWarning: enable_nested_tensor is True, but self.use_nested_tensor is False because encoder_layer.self_attn.batch_first was not True(use batch_first for better inference performance)\n",
      "  warnings.warn(f\"enable_nested_tensor is True, but self.use_nested_tensor is False because {why_not_sparsity_fast_path}\")\n",
      "\n",
      "KeyboardInterrupt\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# !gdown --id 1V8itWtowCYnb2Bc9KlK9SxGff9WwmogA\n",
    "\n",
    "model = SentimentClassifier(len(class_names))\n",
    "model.load_state_dict(torch.load('Pretrained_RoBert_SRL(FC)-tuning.bin'))\n",
    "model = model.to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "KYRPY0C-fFQh",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "len(df_test)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "c7Cckbz8GbDK",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "test_acc, _ = eval_model(\n",
    "  model,\n",
    "  test_data_loader,\n",
    "  loss_fn,\n",
    "  device,\n",
    "  len(df_test)\n",
    ")\n",
    "\n",
    "test_acc.item()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "a0Qemnl0FiEb",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "def get_predictions(model, data_loader):\n",
    "  model = model.eval()\n",
    "  \n",
    "  review_texts = []\n",
    "  predictions = []\n",
    "  prediction_probs = []\n",
    "  real_values = []\n",
    "\n",
    "  with torch.no_grad():\n",
    "    for d in data_loader:\n",
    "\n",
    "      texts = d[\"review_text\"]\n",
    "      input_ids = d[\"input_ids\"].to(device)\n",
    "      attention_mask = d[\"attention_mask\"].to(device)\n",
    "      targets = d[\"targets\"].to(device)\n",
    "      verb = d[\"verb\"].to(device)\n",
    "      A0 = d[\"A0\"].to(device)\n",
    "      A1 = d[\"A1\"].to(device)\n",
    "      AV_num = d['AV_num'].to(device)\n",
    "\n",
    "      outputs = model(\n",
    "        input_ids=input_ids,\n",
    "        attention_mask=attention_mask,\n",
    "        verb = verb,\n",
    "        A0 = A0,\n",
    "        A1 = A1,\n",
    "        AV_num = AV_num\n",
    "      )\n",
    "      if outputs.dim()==1:\n",
    "        outputs = torch.unsqueeze(outputs,0)\n",
    "      _, preds = torch.max(outputs, dim=1)\n",
    "      probs = F.softmax(outputs, dim=1)\n",
    "\n",
    "      review_texts.extend(texts)\n",
    "      predictions.extend(preds)\n",
    "      prediction_probs.extend(probs)\n",
    "      real_values.extend(targets)\n",
    "\n",
    "  predictions = torch.stack(predictions).cpu()\n",
    "  prediction_probs = torch.stack(prediction_probs).cpu()\n",
    "  real_values = torch.stack(real_values).cpu()\n",
    "  return review_texts, predictions, prediction_probs, real_values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "def show_confusion_matrix(confusion_matrix):\n",
    "  hmap = sns.heatmap(confusion_matrix, annot=True, fmt=\"d\", cmap=\"Blues\")\n",
    "  hmap.yaxis.set_ticklabels(hmap.yaxis.get_ticklabels(), rotation=0, ha='right')\n",
    "  hmap.xaxis.set_ticklabels(hmap.xaxis.get_ticklabels(), rotation=30, ha='right')\n",
    "  plt.ylabel('True sentiment')\n",
    "  plt.xlabel('Predicted sentiment');"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "YkPHXF0MGiCh",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "y_review_texts, y_pred, y_pred_probs, y_test = get_predictions(\n",
    "  model,\n",
    "  test_data_loader\n",
    ")\n",
    "\n",
    "print(classification_report(y_test, y_pred, target_names=class_names,digits=4))\n",
    "\n",
    "cm = confusion_matrix(y_test, y_pred)\n",
    "df_cm = pd.DataFrame(cm, index=class_names, columns=class_names)\n",
    "show_confusion_matrix(df_cm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "df = pd.DataFrame([y_review_texts, y_pred.numpy(), y_pred_probs.numpy(), y_test.numpy()]).T\n",
    "df = df.rename(columns={0:'text',1:'prediction',2:'probability',3:'labels'})\n",
    "df.to_csv('Pretrained_RoBert_SRL(FC)-tuning.csv',sep='\\t')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "y_ood_review_texts, y_ood_pred, y_ood_pred_probs, y_ood = get_predictions(\n",
    "  model,\n",
    "  ood_data_loader\n",
    ")\n",
    "\n",
    "print(classification_report(y_ood, y_ood_pred, target_names=class_names,digits=4))\n",
    "\n",
    "ood_cm = confusion_matrix(y_ood, y_ood_pred)\n",
    "df_ood_cm = pd.DataFrame(ood_cm, index=class_names, columns=class_names)\n",
    "show_confusion_matrix(df_ood_cm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "df_ood = pd.read_csv('../data/ood.csv',sep='\\t')\n",
    "# df_ood = df_ood.loc[(df_ood.DATE>='2021-05-05')&(df_ood.DATE<='2021-09-01')]\n",
    "df_ood = df_ood.sort_values(by='DATE')\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "df_ood = df_ood.loc[:4000]\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1.isna()].index)\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1=='[]'].index)\n",
    "for col in ['verb','A0','A1']:\n",
    "  df_ood[col] = df_ood[col].apply(string_to_tuples_list)\n",
    "\n",
    "for col in ['stock_factors','verbA0A1']:\n",
    "  df_ood[col] = df_ood[col].apply(ast.literal_eval)\n",
    "df_ood = mask(df_ood)\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "ood_data_loader = create_data_loader(df_ood, tokenizer, max_len, BATCH_SIZE)\n",
    "\n",
    "y_ood_review_texts, y_ood_pred, y_ood_pred_probs, y_ood = get_predictions(\n",
    "  model,\n",
    "  ood_data_loader\n",
    ")\n",
    "\n",
    "print(classification_report(y_ood, y_ood_pred, target_names=class_names,digits=4))\n",
    "\n",
    "ood_cm = confusion_matrix(y_ood, y_ood_pred)\n",
    "df_ood_cm = pd.DataFrame(ood_cm, index=class_names, columns=class_names)\n",
    "show_confusion_matrix(df_ood_cm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "df_ood = pd.read_csv('../data/ood.csv',sep='\\t')\n",
    "# df_ood = df_ood.loc[(df_ood.DATE>='2021-05-05')&(df_ood.DATE<='2021-09-01')]\n",
    "df_ood = df_ood.sort_values(by='DATE')\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "df_ood = df_ood.loc[:3000]\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1.isna()].index)\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1=='[]'].index)\n",
    "for col in ['verb','A0','A1']:\n",
    "  df_ood[col] = df_ood[col].apply(string_to_tuples_list)\n",
    "\n",
    "for col in ['stock_factors','verbA0A1']:\n",
    "  df_ood[col] = df_ood[col].apply(ast.literal_eval)\n",
    "df_ood = mask(df_ood)\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "ood_data_loader = create_data_loader(df_ood, tokenizer, max_len, BATCH_SIZE)\n",
    "\n",
    "y_ood_review_texts, y_ood_pred, y_ood_pred_probs, y_ood = get_predictions(\n",
    "  model,\n",
    "  ood_data_loader\n",
    ")\n",
    "\n",
    "print(classification_report(y_ood, y_ood_pred, target_names=class_names,digits=4))\n",
    "\n",
    "ood_cm = confusion_matrix(y_ood, y_ood_pred)\n",
    "df_ood_cm = pd.DataFrame(ood_cm, index=class_names, columns=class_names)\n",
    "show_confusion_matrix(df_ood_cm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "df_ood = pd.read_csv('../data/ood.csv',sep='\\t')\n",
    "# df_ood = df_ood.loc[(df_ood.DATE>='2021-05-05')&(df_ood.DATE<='2021-09-01')]\n",
    "df_ood = df_ood.sort_values(by='DATE')\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "df_ood = df_ood.loc[:2000]\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1.isna()].index)\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1=='[]'].index)\n",
    "for col in ['verb','A0','A1']:\n",
    "  df_ood[col] = df_ood[col].apply(string_to_tuples_list)\n",
    "\n",
    "for col in ['stock_factors','verbA0A1']:\n",
    "  df_ood[col] = df_ood[col].apply(ast.literal_eval)\n",
    "df_ood = mask(df_ood)\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "ood_data_loader = create_data_loader(df_ood, tokenizer, max_len, BATCH_SIZE)\n",
    "\n",
    "y_ood_review_texts, y_ood_pred, y_ood_pred_probs, y_ood = get_predictions(\n",
    "  model,\n",
    "  ood_data_loader\n",
    ")\n",
    "\n",
    "print(classification_report(y_ood, y_ood_pred, target_names=class_names,digits=4))\n",
    "\n",
    "ood_cm = confusion_matrix(y_ood, y_ood_pred)\n",
    "df_ood_cm = pd.DataFrame(ood_cm, index=class_names, columns=class_names)\n",
    "show_confusion_matrix(df_ood_cm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "df_ood = pd.read_csv('../data/df_all_year_srl.csv',sep='\\t')\n",
    "# df_ood = df_ood.loc[(df_ood.DATE>='2021-05-05')&(df_ood.DATE<='2021-09-01')]\n",
    "df_ood = df_ood.sort_values(by='DATE')\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "# df_ood = df_ood.loc[:2000]\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1.isna()].index)\n",
    "df_ood = df_ood.drop(df_ood.loc[df_ood.verbA0A1=='[]'].index)\n",
    "for col in ['verb','A0','A1']:\n",
    "  df_ood[col] = df_ood[col].apply(string_to_tuples_list)\n",
    "\n",
    "for col in ['stock_factors','verbA0A1']:\n",
    "  df_ood[col] = df_ood[col].apply(ast.literal_eval)\n",
    "df_ood = mask(df_ood)\n",
    "df_ood = df_ood.reset_index(drop=True)\n",
    "ood_data_loader = create_data_loader(df_ood, tokenizer, max_len, BATCH_SIZE)\n",
    "\n",
    "y_ood_review_texts, y_ood_pred, y_ood_pred_probs, y_ood = get_predictions(\n",
    "  model,\n",
    "  ood_data_loader\n",
    ")\n",
    "\n",
    "print(classification_report(y_ood, y_ood_pred, target_names=class_names,digits=4))\n",
    "\n",
    "ood_cm = confusion_matrix(y_ood, y_ood_pred)\n",
    "df_ood_cm = pd.DataFrame(ood_cm, index=class_names, columns=class_names)\n",
    "show_confusion_matrix(df_ood_cm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "df = pd.DataFrame([y_ood_review_texts, y_ood_pred.numpy(), y_ood_pred_probs.numpy(), y_ood.numpy()]).T\n",
    "df = df.rename(columns={0:'text',1:'prediction',2:'probability',3:'labels'})\n",
    "df.to_csv('Pretrained_RoBert_SRL(FC)_ood.csv',sep='\\t')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "6QZ0EgQoalz2",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# !pip install lit-nlp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "eAeHdVF7c-QF",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# from lit_nlp.api.dataset import Dataset\n",
    "# class MultiNLIData(Dataset):\n",
    "#   \"\"\"Loader for MultiNLI development set.\"\"\"\n",
    "#   def __init__(self, df):\n",
    "#     # Read the eval set from a .tsv file as distributed with the GLUE benchmark.\n",
    "#     # df = pandas.read_csv(path, sep='\\t')\n",
    "#     # Store as a list of dicts, conforming to self.spec()\n",
    "#     self.LABELS = [0,1]\n",
    "#     self._examples = [{\n",
    "#       'sentence': row['DESCRIPTION_EN'],\n",
    "#       # 'hypothesis': row['sentence2'],\n",
    "#       'label': row['LABEL']\n",
    "#       # 'genre': row['genre'],\n",
    "#     } for _, row in df.iterrows()]\n",
    "#   def spec(self):\n",
    "#     return {\n",
    "#       'sentence': lit_types.TextSegment(),\n",
    "#       # 'hypothesis': lit_types.TextSegment(),\n",
    "#       'label': lit_types.CategoryLabel(vocab=self.LABELS),\n",
    "#       # We can include additional fields, which don't have to be used by the model.\n",
    "#       # 'genre': lit_types.Label(),\n",
    "#     }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "l5886G4mdXia",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "background_save": true
    },
    "id": "mrSBCdqO0sUs",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "f-nX4zrOdxpo",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ARdnz5td18VV",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "iMviJZsfdifG",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "8h5I2QKodj8b",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "0-abzg6avOQq",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "flJ1xtWNvYej",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "nBxb2zhWvfaK",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# from absl import app\n",
    "# from absl import flags\n",
    "# from absl import logging\n",
    "\n",
    "# from lit_nlp import dev_server\n",
    "# from lit_nlp import server_flags\n",
    "# from lit_nlp.api import model as lit_model\n",
    "# from lit_nlp.api import types as lit_types\n",
    "# # Use the regular GLUE data loaders, because these are very simple already.\n",
    "# from lit_nlp.examples.datasets import glue\n",
    "# from lit_nlp.lib import utils\n",
    "\n",
    "# import torch\n",
    "# import transformers\n",
    "\n",
    "# # NOTE: additional flags defined in server_flags.py\n",
    "\n",
    "# FLAGS = flags.FLAGS\n",
    "\n",
    "# flags.DEFINE_string(\n",
    "#     \"model_path\",\n",
    "#     \"https://storage.googleapis.com/what-if-tool-resources/lit-models/sst2_tiny.tar.gz\",\n",
    "#     \"Path to trained model, in standard transformers format, e.g. as \"\n",
    "#     \"saved by model.save_pretrained() and tokenizer.save_pretrained()\")\n",
    "\n",
    "\n",
    "# def _from_pretrained(cls, *args, **kw):\n",
    "#   \"\"\"Load a transformers model in PyTorch, with fallback to TF2/Keras weights.\"\"\"\n",
    "#   try:\n",
    "#     return cls.from_pretrained(*args, **kw)\n",
    "#   except OSError as e:\n",
    "#     logging.warning(\"Caught OSError loading model: %s\", e)\n",
    "#     logging.warning(\n",
    "#         \"Re-trying to convert from TensorFlow checkpoint (from_tf=True)\")\n",
    "#     return cls.from_pretrained(*args, from_tf=True, **kw)\n",
    "\n",
    "\n",
    "# class SimpleSentimentModel(lit_model.Model):\n",
    "#   \"\"\"Simple sentiment analysis model.\"\"\"\n",
    "\n",
    "#   LABELS = [0,1]  # negative, positive\n",
    "\n",
    "#   def __init__(self, model_name_or_path):\n",
    "#     self.tokenizer = transformers.AutoTokenizer.from_pretrained(\n",
    "#         model_name_or_path)\n",
    "#     model_config = transformers.AutoConfig.from_pretrained(\n",
    "#         model_name_or_path,\n",
    "#         num_labels=2,\n",
    "#         output_hidden_states=True,\n",
    "#         output_attentions=True,\n",
    "#     )\n",
    "#     # This is a just a regular PyTorch model.\n",
    "#     self.model = _from_pretrained(\n",
    "#         transformers.AutoModelForSequenceClassification,\n",
    "#         model_name_or_path,\n",
    "#         config=model_config)\n",
    "#     self.model.eval()\n",
    "\n",
    "#   ##\n",
    "#   # LIT API implementation\n",
    "#   def max_minibatch_size(self):\n",
    "#     # This tells lit_model.Model.predict() how to batch inputs to\n",
    "#     # predict_minibatch().\n",
    "#     # Alternately, you can just override predict() and handle batching yourself.\n",
    "#     return 16\n",
    "\n",
    "#   def predict_minibatch(self, inputs):\n",
    "#     # Preprocess to ids and masks, and make the input batch.\n",
    "#     encoded_input = self.tokenizer.batch_encode_plus(\n",
    "#         [ex[\"sentence\"] for ex in inputs],\n",
    "#         return_tensors=\"pt\",\n",
    "#         add_special_tokens=True,\n",
    "#         max_length=200,\n",
    "#         padding=\"longest\",\n",
    "#         truncation=\"longest_first\")\n",
    "\n",
    "#     # Check and send to cuda (GPU) if available\n",
    "#     if torch.cuda.is_available():\n",
    "#       self.model.cuda()\n",
    "#       for tensor in encoded_input:\n",
    "#         encoded_input[tensor] = encoded_input[tensor].cuda()\n",
    "#     # Run a forward pass.\n",
    "#     with torch.no_grad():  # remove this if you need gradients.\n",
    "#       out: transformers.modeling_outputs.SequenceClassifierOutput = \\\n",
    "#           self.model(**encoded_input)\n",
    "\n",
    "#     # Post-process outputs.\n",
    "#     batched_outputs = {\n",
    "#         \"probas\": torch.nn.functional.softmax(out.logits, dim=-1),\n",
    "#         \"input_ids\": encoded_input[\"input_ids\"],\n",
    "#         \"ntok\": torch.sum(encoded_input[\"attention_mask\"], dim=1),\n",
    "#         \"cls_emb\": out.hidden_states[-1][:, 0],  # last layer, first token\n",
    "#     }\n",
    "#     # Return as NumPy for further processing.\n",
    "#     detached_outputs = {k: v.cpu().numpy() for k, v in batched_outputs.items()}\n",
    "#     # Unbatch outputs so we get one record per input example.\n",
    "#     for output in utils.unbatch_preds(detached_outputs):\n",
    "#       ntok = output.pop(\"ntok\")\n",
    "#       output[\"tokens\"] = self.tokenizer.convert_ids_to_tokens(\n",
    "#           output.pop(\"input_ids\")[1:ntok - 1])\n",
    "#       yield output\n",
    "\n",
    "#   def input_spec(self) -> lit_types.Spec:\n",
    "#     return {\n",
    "#         \"sentence\": lit_types.TextSegment(),\n",
    "#         \"label\": lit_types.CategoryLabel(vocab=self.LABELS, required=False)\n",
    "#     }\n",
    "\n",
    "#   def output_spec(self) -> lit_types.Spec:\n",
    "#     return {\n",
    "#         \"tokens\": lit_types.Tokens(),\n",
    "#         \"probas\": lit_types.MulticlassPreds(parent=\"label\", vocab=self.LABELS),\n",
    "#         \"cls_emb\": lit_types.Embeddings()\n",
    "#     }\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "B64IFx5g461l",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# dataset = MultiNLIData(df_train.sample(1800))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "qR0nbr94v2xz",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# datasets = {\"sst_dev\": dataset}\n",
    "# models = {\"sst\": SimpleSentimentModel(\"/content/drive/MyDrive/model/best_model/\")}\n",
    "# # models = {\"sst\": SimpleSentimentModel(\"bert-base-uncased\")}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "WR8VwsH9v4l8",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# from lit_nlp import notebook\n",
    "# widget = notebook.LitWidget(models, datasets, height=800)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "wNPctrXDBQSM",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# mm = models[\"sst\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "lHX6hJtVCAuX",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# mm.model.config"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "cihtCCxC3ftN",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# widget.render()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "h5c4S99U5UOS",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "# dataset.LABELS\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "WxSfPfOF7dNo",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "UHZ2GHS2YPJx",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "dZufJ9IYxafN",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "SUEQvcwK5884",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "UlBpR4nZ8Pm4",
    "is_executing": true
   },
   "outputs": [],
   "source": [
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "KOfzGtQA13Lk",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "WgHgeymrvwfF"
   },
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "vzRGjrB78JEU",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "hisO325IxQp8",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "Kbe4pgmh1gQY",
    "is_executing": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "collapsed_sections": [],
   "name": "RoBert_SRL(AVG).ipynb",
   "provenance": [
    {
     "file_id": "1xvnsGah2Q-vSoeeYiJUYa9goPinvHJ7u",
     "timestamp": 1633470040515
    },
    {
     "file_id": "1UmCPDjec7zH3RdCY3Hdite8oomF7nmf9",
     "timestamp": 1633290928316
    },
    {
     "file_id": "1w9vwLdm73DBRpQkWEjXqs5q-sfG5CFRP",
     "timestamp": 1633210989154
    },
    {
     "file_id": "1dItOUA_nHj-f307fzTileirMZodw9QQA",
     "timestamp": 1633052138904
    },
    {
     "file_id": "1Oo-71ViOwxENoHeitS3_bKCwW5v34UxN",
     "timestamp": 1632660498277
    },
    {
     "file_id": "1el47BmEzo31ysADRwzhNG8eWTFAGBwSd",
     "timestamp": 1632523116920
    },
    {
     "file_id": "1_JaZBt7ogFAsddWCCG0LcCdgNRAxqtFk",
     "timestamp": 1632443626664
    },
    {
     "file_id": "19E0FxMVVPc7sOJKBKGMO92IFUiH9i8Nq",
     "timestamp": 1631945855961
    },
    {
     "file_id": "1-IQze66iqGbhkSN5Ht7pAfMMsY-XRwDI",
     "timestamp": 1631743166519
    },
    {
     "file_id": "1WejxgDbBCZ7I2Y_ODwi3kgRtrnkLvn-b",
     "timestamp": 1631518058457
    },
    {
     "file_id": "1npRyGEmBJbLWSua7ANgxcMxsQsuWXnKG",
     "timestamp": 1631425160358
    }
   ],
   "version": ""
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
